以mysql資料庫索引為例,參考文章為:mysql索引背後的資料結構及原理
索引(index)是幫助mysql高效獲取資料的資料結構。在資料之外,資料庫系統還維護著滿足特定查詢演算法的資料結構,這些資料結構以某種方式引用(指向)資料,這樣就可以在這些資料結構上實現高階查詢演算法。這種資料結構,就是索引。
圖1展示了一種可能的索引方式。左邊是資料表,一共有兩列七條記錄,最左邊的是資料記錄的實體地址(注意邏輯上相鄰的記錄在磁碟上並不是一定物理相鄰的)。為了加快col2的查詢,可以維護以右邊所示的二叉查詢樹,每個節點分辨包含索引鍵值和乙個指向對應資料記錄實體地址的指標,這樣就可以運用二叉查詢樹在o(logn)的複雜度內 獲取到相應資料。
目前大部分資料庫系統及檔案系統都採用b-tree或其變種b-tree作為索引結構。
b-tree
1、d為大於1的正整數,稱為b-tree的度
2、h為乙個正整數,稱為b-tree的高度
3、每個非葉節點由n-1個key和n個指標構成,其中d<=n<=2d
4、每個葉子節點最少包含乙個key和兩個指標,最多包含2d-1個key和2d個指標,葉節點的指標均為null。
5、所有葉節點具有相同的深度,等於樹高h。
6、乙個節點中的key從左到右非遞減排列。
乙個度為d的b-tree,設其索引n個key,則其樹高h的上限為
logd((n+1)/2),檢索乙個key,其查詢節點個數的漸進複雜度為o(logdn)。
b+tree
與b-tree相比,b+tree有以下不同點:
1、每個節點的指標上限為2d而不是2d+1
2、內節點不儲存data,只儲存key;葉子節點不儲存指標
由於並不是所有節點都具有相同的域,因此b+tree中葉節點和內節點一般大小不同。這點與b-tree不同,雖然b-tree中不同節點存放的key和指標可能數量不一致,但是每個節點的域和上限是一致的,所以在實現中b-tree往往對每個節點申請同等大小的空間。
帶有順序訪問指標的b+tree
在b+tree的每個葉子節點增加乙個指向相鄰葉子節點的指標,解就形成了帶有順序訪問指標的b+tree。做這個優化的目的是為了提高區間訪問效能,例如圖4中如果要查詢key為從18到49的所有資料記錄,當找到18後,只需要順著節點和指標遍歷就可以一次性訪問到所有資料節點,極大提高了區間查詢效率。
為什麼使用b-tree(b+tree)
一般來說,索引本身很大,不可能全部儲存在記憶體中,因此索引往往以索引檔案的形式儲存在磁碟上。這樣的話,索引查詢過程就要產生磁碟io消耗,所以評價乙個資料結構作為索引的優劣最重要的指標就是在查詢過程中磁碟io操作次數的漸進複雜度。換句話說,索引的結構組織要儘量減少查詢過程中磁碟io的訪問次數。
主存訪問的時間與訪問次數呈線性關係,因為不存在機械操作,兩次訪問的資料的「距離」不會對時間有任何影響。
為了提高效率,儘量減少磁碟io,磁碟往往不是嚴格按需讀取,而是每次都會預讀,即使只需要乙個位元組,磁碟也會從這個位置開始,順序向後讀取一定長度的資料放入記憶體。這樣的理論依據是區域性性原理。
b-/+tree索引的效能分析
根據b-tree的定義,可知檢索一次最多需要訪問h個節點。利用了磁碟預讀原理,將乙個節點的大小設為等於乙個頁,這樣每個節點只需要乙個io就可以完全載入。每次新建節點時,直接申請乙個頁的空間,這樣就保證乙個節點物理上也儲存在乙個頁裡。
b-tree中一次檢索最多需要h-1次io(根節點常駐記憶體),漸進複雜度為o(h)=o(logdn),一般實際應用中,度d是非常大的數字,通常超過100,因此h非常小。
所以b-tree作為索引結構效率是非常高的。
而紅黑樹,h明顯要深的多。由於邏輯上很近的節點(父子)物理上可能很遠,無法利用區域性性,所以紅黑樹的io漸進複雜度為o(h),效率明顯比b-tree差很多。
b+tree更適合做索引,原因和內節點出度d有關。d越大,索引效能越好,而度d的上限取決於節點內key和data的大小。由於b+tree內節點丟掉了data域,因此可以擁有更大的度,擁有更好的效能。
myisam索引實現:
myisam引擎使用b+tree作為索引結構,葉節點data域存放的是資料記錄的位址。
主索引和輔助索引結構上沒有任何區別,只是主索引要求key是唯一的,而輔助索引的key可以重複。
因此,myisam中索引檢索的演算法為首先按照b+tree搜尋演算法搜尋索引,如果指定的key存在,則取出其data域的值,然後以data域的值為位址,讀取相應資料記錄。
myisam的索引方式也叫作「非聚集」的。
innodb索引實現
也使用b+tree作為索引結構,但實現方式與myisam不同。
1、innodb的資料檔案本身就是索引檔案。myisam索引檔案和資料檔案分離,索引檔案僅儲存資料記錄的位址。而innodb中,表資料檔案本身就是按b+tree組織的乙個索引結構,這棵樹的葉節點data儲存了完整的資料記錄。這個索引的key是資料表的主鍵,因此innodb表資料檔案本身就是主索引。
innodb主索引(同時也是資料檔案)的示意圖,可以看到葉節點包含了完整的資料記錄,這種索引叫作聚集索引。
因為innodb的資料檔案本身要按主鍵聚集,所以innodb要求表必須有主鍵(myisam可以沒有)。
2、與myisam索引不同的是innodb的輔助索引data域儲存相應記錄主鍵的值而不是位址。換句話說,innodb的所有輔助索引都引用主鍵作為data域。
聚集索引這種實現方式使得按主鍵的搜尋十分高效,但是輔助索引搜尋需要檢索兩邊索引:首先檢索輔助索引獲得主鍵,然後用主鍵到主索引中檢索獲得記錄。
innodb為什麼不建議使用過長的字段作為主鍵?因為索引輔助索引都引用主索引,過長的主索引會令輔助索引變得過大。
用非單調的字段作為主鍵在innodb中不是個好主意。因為innodb資料檔案本身是一顆b+tree,非單調的主鍵會造成在插入新記錄時資料檔案為了維持b+tree的特性而頻繁的**調整,十分低效,而使用自助字段作為主鍵是乙個很好的選擇。
資料庫 資料庫索引
索引是儲存引擎用於快速找到記錄的一種資料結構。索引以檔案的形式儲存在磁碟中。索引可以包含乙個或多個列的值。儲存引擎查詢資料的時候,先在索引中找對應值,然後根據匹配的索引記錄找到對應的資料行。1.b tree索引 2.雜湊索引 myisam和innodb儲存引擎 只支援btree索引,也就是說預設使用...
資料庫mysql索引 資料庫 mysql索引
mysql 索引 mysql索引的建立對於mysql的高效執行是很重要的,索引可以大大提高mysql的檢索速度。打個比方,如果合理的設計且使用索引的mysql是一輛蘭博基尼的話,那麼沒有設計和使用索引的mysql就是乙個人力三輪車。索引分單列索引和組合索引。單列索引,即乙個索引只包含單個列,乙個表可...
資料庫索引
索引 索引列唯一索引 主鍵索引 聚簇索引和非聚簇索引 如何建立索引 如何刪除索引 使用索引可快速訪問資料庫表中的特定資訊。索引是對資料庫表中一列或多列的值進行排序的一種結構,例如 employee 表的姓 lname 列。如果要按姓查詢特定職員,與必須搜尋表中的所有行相比,索引會幫助您更快地獲得該資...