1. 程式人生 > 資料庫 >《高效能MySQL》閱讀-高效能索引策略

《高效能MySQL》閱讀-高效能索引策略

【四非凡人】:才德兼備是聖人,無才有德是賢人,
有才無德是小人,才德俱失是庸人。

高效能的索引策略

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