Mysql innodb索引與查詢優化

1、 引言

概要mysql

(1)  innodb索引類型與B+樹算法

(2)  索引使用注意事項sql

(3)  車點評業務表索引優化案例數據庫

 

問題緩存

(1)  InnoDb索引爲何要用b+樹?性能

(2)  彙集索引與普通索引有什麼區別?優化

(3)  爲何主鍵最好是自增?spa

(4)  組合索引有什麼優點?指針

(5) 有哪些實際業務場景索引搞不定? 索引

 

2、 innodb索引類型與B+樹

INNODB主要有幾種索引:B+樹索引,自適應哈希索引,全文索引 ,覆蓋索引。
B+樹索引是一種多叉平衡查找樹。
自適應哈希索引是mysql對於頻繁查詢的數據採起的hash存儲優化,用戶沒法選擇設置。
全文索引主要用於全文檢索使用。
覆蓋索引說的是查詢的字段都屬於同一個索引字段,這樣效率很是高。

 

查找樹

      查找樹主要有:二叉查找樹(Binary Search Tree),平衡二叉查找樹(Balanced Binary Search Tree),紅黑樹(Red-Black Tree ),B-tree/B+-tree/ B*-tree (B~Tree)。前三者是典型的二叉查找樹結構,其查找的時間複雜度O(log2N)與樹的深度相關,那麼下降樹的深度天然會提升查找效率。

 

B/B+/B*

 

B樹

 

 

B+樹

 

 

全部的葉子結點中包含了所有關鍵字的信息,及指向含有這些關鍵字記錄的指針,且葉子結點自己依關鍵字的大小自小而大的順序連接。

數據庫索引採用B+樹的主要緣由是: B樹在提升了磁盤IO性能的同時並無解決元素遍歷的效率低下的問題。正是爲了解決這個問題,B+樹應運而生。B+樹只要遍歷葉子節點就能夠實現整棵樹的遍歷。並且在數據庫中基於範圍的查詢是很是頻繁的,而B樹不支持這樣的操做(或者說效率過低)。

 

B*樹

 

 

和B+樹的主要區別:

一、B*樹中非根和非葉子結點都有指向兄弟的指針;

二、B*樹定義了葉子結點關鍵字個數至少爲(2/3)*M,即塊的最低使用率爲2/3(代替B+樹的1/2)

 

彙集索引和普通索引

 

 

 

一、主鍵和普通索引都是B+樹索引

二、主鍵的葉子節點是:數據;普通索引的葉子節點是:主鍵的值

三、普通索引的檢索須要通過兩次B+樹查找:

     I)經過普通索引,找到:主鍵key

     II)經過主鍵key,查找到元素

 

自適應hash索引

 Innodb存儲引擎會監控對錶上二級索引的查找,若是發現某二級索引被頻繁訪問,二級索引成爲熱數據,創建哈希索引能夠帶來速度的提高。常常訪問的二級索引數據會自動被生成到hash索引裏面去(最近連續被訪問三次的數據),自適應哈希索引經過緩衝池的B+樹構造而來,所以創建的速度很快。

自適應hash索引只適用於等值查詢。

INNODB如何創建彙集索引

1)有主鍵,則INNODB使用它做爲彙集索引。

2)未定義主鍵,INNODB選第一個非NULL的惟一索引列,使用它做爲彙集索引。

3)若是1)、2)都沒有,Mysql自動添加一個不可見不可引用的6byte大小的rowid做爲彙集索引.

 

是自增



     若是表使用自增主鍵,那麼每次插入新的記錄,記錄就會順序添加到當前索引節點的後續位置,當一頁寫滿,就會自動開闢一個新的頁

若是使用非自增主鍵(若是身份證號或學號等),因爲每次插入主鍵的值近似於隨機,所以每次新紀錄都要被插到現有索引頁得中間某個位置,此時MySQL不得不爲了將新記錄插到合適位置而移動數據,甚至目標頁面可能已經被回寫到磁盤上而從緩存中清掉,此時又要從磁盤上讀回來,這增長了不少開銷,同時頻繁的移動、分頁操做形成了大量的碎片,獲得了不夠緊湊的索引結構,後續不得不經過OPTIMIZE TABLE來重建表並優化填充頁面。

 

普通索引的葉子點內容

       存儲的是主鍵的值。好處以下

       輔助索引使用主鍵做爲"指針" 而不是使用地址值做爲指針的好處是,減小了當出現行移動或者數據頁分裂時輔助索引的維護工做,使用主鍵值看成指針會讓輔助索引佔用更多的空間,換來的好處是InnoDB在移動行時無須更新輔助索引中的這個"指針"。

 

普通索引的葉子點空洞

B*樹定義了葉子結點關鍵字個數至少爲(2/3)*M,即塊的最低使用率爲2/3

B+樹的最低使用率是1/2,這是由樹的分裂算法決定的。

 

B+樹的分裂:當一個結點滿時,分配一個新的結點,並將原結點中1/2的數據複製到新結點,最後在父結點中增長新結點的指針;
                 

B*樹的分裂:當一個結點滿時,若是它的下一個兄弟結點未滿,那麼將一部分數據移到兄弟結點中,再在原結點插入關鍵字,最後修改父結點中兄弟結點的關鍵字(由於兄弟結點的關鍵字範圍改變了);

                      若是兄弟也滿了,則在原結點與兄弟結點之間增長新結點,並各複製1/3的數據到新結點,最後在父結點增長新結點的指針;
因此,B*樹分配新結點的機率比B+樹要低,空間使用率更高; 

 

每一次數據頁分裂,都會致使葉子節點空洞的產生。

COUNT查詢較慢緣由以及優化    

    count指令實現上採用實時統計方式,要麼經過彙集索引統計,要麼經過二級索引統計
    在無可用的二級索引狀況下,執行count會使MySQL掃描全表數據,當數據中存在大字段或字段較多時候,其效率很是低下(每一個頁只能包含較少的數據條數,須要訪問的物理頁較多)
   
      二級索引存儲的數據爲指定字段的值與主鍵值。當咱們經過二級索引統計數據的時候,無需掃描數據文件;

      因此,能夠創建合適的單子段普通索引,提升COUNT統計效率
     

合索引優點

(1) 知足最左前綴的查詢,均可以用到索引。

(2) 覆蓋索引查詢,效率更快。

 

3、 索引使用注意事項

 

(1)  儘可能選擇區分度高的列做爲索引。

      區分度的公式是count(distinct col)/count(*),表示字段不重複的比例,比例越大咱們掃描的記錄數越少,惟一鍵的區分度是1

(2) 選用自增ID做爲主鍵。

(3) 組合索引的創建須要進行仔細分析;

    1)、正確選擇組合索引中的主列字段,通常是選擇性較好的字段;


    2)、組合索引的幾個字段是否常常同時以AND方式出如今Where子句中?
          若是是,則能夠創建複合索引;不然考慮單字段索引;


    3)、若是複合索引中包含的字段常常單獨出如今Where子句中,則分解爲多個單字段索引;


    4)、若是複合索引所包含的字段超過3個,那麼仔細考慮其必要性,考慮減小複合的字段;

(4) 頻繁進行數據操做的表,不要創建太多的索引;

(5) 刪除無用的索引,避免對執行計劃形成負面影響;

(6) 應儘可能避免在WHERE子句中對字段進行NULL值判斷,不然將致使引擎放棄使用索引而進行全表掃描。

(7) 字符字段只建前綴索引, 最好不要作主鍵。

(8) 使用同類型進行比較, 不然不會用到索引。

(9)  儘可能避免在WHERE子句中使用!= 或 <>,not like 操做符,不然將引擎放棄使用索引而進行全表掃描。

(10) 索引不會包含有NULL值的列。

(11) 單表索引建議控制在5個之內。

(12) 何時不要使用索引?

    常常增刪改的列不要創建索引.

    有大量重複的列不創建索引.

    表記錄太少不要創建索引;

...

相關文章
相關標籤/搜索