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) 何時不要使用索引?
常常增刪改的列不要創建索引.
有大量重複的列不創建索引.
表記錄太少不要創建索引;
...