《高效能MySQL》閱讀-高效能索引策略
阿新 • • 發佈:2021-01-19
【四非凡人】:才德兼備是聖人,無才有德是賢人,
有才無德是小人,才德俱失是庸人。
高效能的索引策略
- 獨立的列
① 是指索引列不能是表示式的一部分,也不能是函式的引數(MySQL8.0版本之後可以有函式索引了) - 字首索引和索引的選擇
① 有時索引列字元非常的長,這會讓索引變得大且慢
② 通常可以選擇使用索引的部分字元,這樣可以大大節約索引空間,這樣同樣也降低了索引的選擇性
**索引的選擇性:**不重複的索引值(也稱為基數,cardinality)和資料表記錄總數(#T)的比值,範圍從1/(#T)到1之間。索引的選擇性越高則查詢效率越高,因為選擇性高的索引可以讓MySQL在查詢時過濾掉更多的行,唯一索引的選擇性是1 ,這是最好的索引選擇性,效能也是最好的
④ 要選擇足夠長的字首以保證較高的選擇性,同時又不能太長(以便節約空間)。字首應該足夠長,以使得字首索引的選擇性接近於索引整個列。換句話說,字首的“基數”應該接近於完整列的“基數” - 多列索引
- 在多個列行建立獨立的單列索引,大部分情況下並不能提高MySQL的查詢效能。MySQL5.0和更新版本引入了一種“合併索引” 的策略,一定程度上可以使用表上的多個單列索引來定位指定的行。
- 合併索引的變種:OR條件的聯合,AND條件的相交,組合前兩種情況的聯合及相交。
- 糟糕的索引:
① 當出現伺服器對多個索引 做相交操作時,通常意味著需要一個包含所有相關列的多列索引,而不是多個獨立的單列索引
② 當伺服器需要對多個索引聯合操作時,通常需要耗費大量CPU和記憶體資源在演算法的快取、排序和合並操作上
- 選擇合適的索引列順序
- 在一個多列B-Tree索引中,索引列的順序意味著索引首先按照最左列進行排序,其次是第二列,等等
- 選擇性最高的列放到索引最前列。
- 聚簇索引
- 聚簇索引並不是一種單獨的索引型別,而是一種資料儲存方式。 具體的細節依賴於其實現方式,但InnoDB的聚簇索引實際上在同一個結構中儲存了B-Tree索引和資料行
- 當表有聚簇索引時,它的資料行實際上儲存在索引的葉子頁中。術語“聚簇”表示資料行和相鄰的鍵值緊湊的儲存在一起。
- 因為無法同時把資料行存放在兩個不同的地方,所以一個表只能有一個聚簇索引
- 因為是儲存引擎負責實現索引,因此不是所有的儲存引擎都支援聚簇索引
- InnoDB通過主鍵聚集資料,如果沒有主鍵,InnoDB會選擇一個唯一的非空索引代替。如果這樣的索引也沒有,InnoDB會隱式定義一個主鍵來作為聚簇索引;
- InnoDB只聚集在同一個頁面中的記錄,包含相鄰鍵值的頁面可能會相聚很遠
- 聚集資料的優點:
① 可以把資料儲存在一起
② 資料訪問更快。聚簇索引將索引和資料儲存在同一個B-Tree中,因此從聚簇索引中獲取資料通常比在非聚簇索引中查詢的要快
③ 使用覆蓋索引掃描的查詢可以直接使用頁節點中的主鍵值 - 聚簇索引的缺點
① 聚簇資料最大限度地提高了I/O密集型應用的效能,但如果資料全部都放在記憶體中,則訪問的順序就沒有那麼重要了,聚簇索引也就沒有什麼優勢了
② 插入速度嚴重依賴於插入順序。
③ 更新聚簇索引列的代價很高。因為會槍支罪InnoDB將每個被更新的行移動到新的位置
④ 基於聚簇索引的表在插入新行,或者主鍵被更新導致需要移動行的時候,可能面臨“頁分裂”的問題。當行的主鍵值要求必須將這一行插入到某個已滿的頁中時,儲存引擎會將該頁分裂成兩個頁面來容納該行,這就是一次頁分裂操作,頁分裂會導致表佔用更多的磁碟空間
⑤ 聚簇索引可能導致全表掃描變慢,尤其是行比較稀疏,或者由於頁分裂導致資料儲存不連續的時候
⑥ 二級索引(非聚簇索引)可能比想象的要更大,因為二級索引的葉子節點包含了引用列的主鍵列
⑦ 二級索引查詢需要兩次索引查詢,而不是一次