如何設計一個關系型數據庫


如何設計一個關系型數據庫

索引模塊

為什么要使用索引

B+Tree

1549777435670

  • 非葉子節點的字數指針與關鍵字的個數相同
  • 非葉子節點的字數指針P[i],指向關鍵字值[K[i],K[i+1]]的子樹
  • 非葉子節點僅用來索引,數據保存在葉子節點中
  • 所有葉子節點均有一個鏈指針指向下一個葉子節點(方便做索引)

結論

B+Tree更加適合用來做存儲索引

  • B+樹的磁盤讀寫代價更低
  • B+樹的查詢效率更加穩定
  • B+樹更有利於對數據庫的掃描

Hash索引

1549777628663

buckets是桶

缺點

  • 僅僅滿足“=”,“IN”,不能用於范圍查詢
  • 無法被用來避免數據的排序操作(hashcode是經過hash函數后得出的)
  • 不能利用部分索引鍵查詢
  • 不能避免表掃描
  • 遇到大量Hash相等的情況下不能比B-Tree的索引高

entries在Java中實現有紅黑樹和普通數組兩種形式

BitMap索引

密集索引和稀疏索引的區別

  • 密集索引文件中的每個搜索碼都對應一個索引值
  • 稀疏索引文件只為索引碼的某些值創建索引項

1549778063124

InnoDB

  • 若一個主鍵被定義,則該主鍵被作為密集索引
  • 若沒有主鍵被定義,該表的第一個唯一非空索引則作為密集索引
  • 若不滿足以上條件,innodb內部會自動生成一個隱藏主鍵(密集索引)
  • 非主鍵索引存儲相關鍵位和其對應的主鍵值,包含兩次查找

![1549778755317].\mg\1549778755317.png)

如何定位並優化慢查詢sql

如何優化mysql查詢的查詢效率

show variables like '%quer%';
show status like '%slow_queries%';

-- 設置
set global slow_query_log=on;

-- 修改最長查詢時間
set global long_query_time = 1;
-- 查詢
select name from person_info_large order by name desc;

Explain關鍵字段

type

index:為帶有索引的掃描方式

all:為全表掃描的方式

排序的耗時從低到高的順序:index>all

extra

1549779520141

聯合索引的最左匹配原則的成因

1549780456266

Mysql創建聯合索引(Union Index)時會以Order By A,Order By B的順序,對於A來說所有data rows 都是有序的,但是對於B來說卻不一定。所以必須准許最左匹配原則

對於聯合索引(a,b,c,d)來說,在Mysql解析到(<,>,between and ,like)等范圍查詢語句后,如果后方還有列需要查詢會放棄索引查詢,例如a=1,b=2,c>3,d=5就不會采用索引的方式查詢如果改為a=1,b=2,d=5,c>3就會采用索引,對於第一種情況Mysql的查詢解析器會自動優化,也就是說abc是可以亂序的

緩存模塊

MyISAM和InnoDB

  • InnoDB默認為行級鎖,支持表級
  • MyISAM默認是表級,不支持行級鎖

MyISAM適合的場景

  • 頻繁執行全表count語句
  • 對數據進行增刪改的頻率不高,查詢很頻繁的(這是因為讀寫鎖的原因造成的,讀鎖是共享的S鎖,寫鎖是互斥的X鎖)
  • 沒有事務

InnoDB適合的場景

  • 數據增刪改查都非常頻繁
  • 可靠性高可以支持事務

數據庫的鎖分類

  • 按鎖的粒度划分,可分為表級鎖、行級鎖、葉級鎖
  • 按鎖級別划分,可分為共享鎖S、排它鎖X
  • 按加鎖方式划分,可分為自動鎖、顯示鎖
  • 按操作划分,可划分為DML鎖、DDL鎖
  • 按使用方式划分,可分為樂觀鎖(使用時間戳或者序列化號)、悲觀鎖

數據庫事務的四大特性 ACID

  • 原子性(Atomic):事務包含的操作要么全部完成要么不做
  • 一致性(Consistency):事務必須使數據庫從一個一致性狀態變化到另一個一致性狀態
  • 隔離性(Isolation):一個事務的執行不能被其他事務干擾,多個事務的並發執行是不會相互干擾。
  • 持久性(Durability):已提交事務對數據庫的修改是永久存在的

數據庫定義的錯誤類型

1、臟讀

​ 臟讀是指在事務處理過程中讀取了另一個未提交事務的數據。

​ 當一個事務正在多次修改某個數據,而這個事務的多次修改均為提交,這時一個並發的事務訪問該數據,就會造成兩個事務獲取的數據不一致。

2、不可重復讀

​ 不可重復讀是指對於數據庫的某個數據,一個事務范圍內多次查詢卻返回了不同的值。

​ 例如事務T1在讀取某一數據,而事務T2立馬修改了這個數據並且事務提交給數據庫,事務T1再次讀取這個數據發現數據與之前的數據不相同,發生臟讀。

3、幻讀(虛讀)

​ 幻讀是事務非獨立執行時發生的一種現象。例如事務T1對一個表中的所有行的某個數據項做了從“1”修改到“2”的操作,這是事務T2對表中插入一個數據項“1”,T1查看剛剛修改的數據,會發現還有一行沒有修改,其實是T2添加進來的,就好像發生了幻覺一樣,這就是發生了幻讀。

​ 幻讀和不可重復讀都是讀取了另一條已經提交了的事務,所不同的是臟讀針對的是對一個數據項(的觀察),而幻讀是對一批數據整體(比如數據個數)。

MySql數據庫隔離級別

  1. Serializable(串行化):可避免臟讀、不可重復讀、幻讀
  2. Repeatable Read (可重復讀 MySQL默認級別):可避免臟讀、不可重復讀
  3. Read Committed (讀已提交):可避免臟讀
  4. Read Uncommitted (讀未提交):最低級別,任何情況都不能保證

語法部分

Group By

  • 滿足“select字句中的列名必須為分組列或列函數“
  • 列函數每組返回一個值

JVM

ClassLoader類型

  • BootstrapClassLoader 系統類加載器:C++編寫,加載java.*,負責加載放在<JAVA_HOME>\lib目錄中的,被-Xbootclasspath參數所指定的路徑中,並且是虛擬機表示的類庫,用戶無法直接使用;
  • ExtClassLoader 拓展類加載器:Java編寫,加載javax.*,該類加載器由sun.misc.Launcher$AppClassLoader實現。負責加載<JAVA_HOME>\lib\ext目錄中的,或者被java.ext.dirs系統變量中指定的目錄的所有類庫,用戶可以直接使用;
  • AppClassLoader 用戶類加載器:加載程序所在目錄;
  • 用戶自定義類加載器:加載用戶指定的目錄;

Class.forName()和ClassLoader.loadClass();

主要區別在於是否進行鏈接(Java裝入類中的一步)

Class.loadClass(className,false);

public static Class<?> forName(String name, boolean initialize,
                                   ClassLoader loader)
        throws ClassNotFoundException

Class.forName(className)方法,內部實際調用的方法是 Class.forName(className,true,classloader);

第2個boolean參數表示類是否需要初始化, Class.forName(className)默認是需要初始化。

一旦初始化,就會觸發目標對象的 static塊代碼執行,static參數也也會被再次初始化。

ClassLoader.loadClass(className)方法,內部實際調用的方法是 ClassLoader.loadClass(className,false);

第2個 boolean參數,表示目標對象是否進行鏈接,false表示不進行鏈接,由上面介紹可以,

不進行鏈接意味着不進行包括初始化等一些列步驟,那么靜態塊和靜態對象就不會得到執行


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM