MySQL中,索引是儲存在引擎層而不是伺服器層實現的。
B-Tree索引,它使用B-Tree資料結構來儲存資料。
而MySQL的B-Tree索引雖然名字是BTree,但是InnoDB使用的是B+Tree資料結構實現的。
索引並不總是最好的解決方案。只有當索引幫助儲存引擎快速查詢到記錄帶來的好處大於其額外的工作時,索引才有效的。
https://juejin.im/post/6844903845554814983
正確的建立和使用索引是實現高效能查詢的基礎。
如果查詢中的列不是獨立的,則MySQL不會使用索引。獨立的列
指索引列不能是表示式的一部分,也不能是函數的引數。我們應該簡化WHERE
條件,始終將索引列單獨放在比較符號的一側
在多個列上建立獨立的單列索引大部分情況下不能提高MySQL的查詢效能。MySQL5.0和更新版本引入了一種叫「索引合併」的策略,一定程度上可以使用表上的多個單列索引來定位指定的行。
即在MySQL5.0後,MySQL並不是一次查詢只能使用一個索引了,可以同時使用多個索引
MySQL會使用這類技術優化複雜查詢,但實際上更多時候說明了表上的索引建得很糟糕:
AND
條件),通常意味著需要一個包含所有相關列的多列索引,而不是多個獨立的單列索引OR
條件),通常需要耗費大量CPU和記憶體資源在演演算法的快取、排序和合並操作上。特別是當其中有些索引的選擇性不高,需要合併掃描返回的大量資料的時候查詢成本
中,優化器只關心隨機頁面讀取。這會使得查詢的成本被「低估「,導致該執行計劃還不如走全表掃描。這樣做不但會消耗更多的CPU和記憶體資源,還可能會影響查詢的並行性。正確的順序依賴於使用該索引的查詢,並且同時需要考慮如何更好的滿足排序和分組的需要。
在一個多列索引中,索引列的順序意味著索引首先按照最左列進行排序,其次是第二列。。。
對於如何選擇索引的列順序有一個經驗法則:將選擇性最高的列放到索引最前列
聚簇索引並不是一種單獨的索引型別,而是一種資料儲存方式。具體的細節依賴於其實現方式,但InnoDB的聚簇索引實際上在同一個結構中儲存了B-Tree索引和資料行。
InnoDB將通過主鍵聚集資料。
如果沒有定義主鍵,InnoDB會選擇一個唯一的非空索引代替。如果沒有這樣的索引,InnoDB會隱式定義一個主鍵來作為聚簇索引。
InnoDB只聚集在同一個頁面中的記錄。
聚集的資料有一些重要的優點
:
同時,聚簇索引也有一些缺點
:
OPTIMIZE TABLE
命令重新組織一下表。「頁分裂」
的問題。當行的主鍵值要求必須將這一行插入到某一個已滿的頁中時,儲存引擎會將該頁分裂成兩個頁面來容納該行,這就是一次頁分裂操作。頁分裂會導致表佔用更多的磁碟空間。InnoDB的二級索引和聚簇索引很不相同。
InnoDB二級索引的葉子節點中儲存的不是「行指標」,而是主鍵值,並以此作為指向行的「指標」。
這樣策略減少了當行移動或者資料頁分裂時二級索引的維護工作。只用主鍵值當做指標會讓二級索引佔用更多的空間,換來的好處是,InnoDB在移動行時無須更新二級索引中的這個「指標」
新行的主鍵值不一定比之前插入的大,所以InnoDB無法簡單的總是把新行插入到索引的最後,而是需要為新的行尋找合適的位置——通常是已有資料的中間位置——並且分配空間。這會增加很多額外的工作,並導致資料分佈不夠優化。下面是總結的一些缺點:
在把這些隨機值載入到聚簇索引以後,也許需要做一次OPTIMIZE TABLE
來重建表並優化頁的填充
對於高並行工作負載,在InnoDB中按主鍵順序插入可能會造成明顯的爭用。主鍵的上界會成為「熱點」。因為所有的插入都發生在這裡,所以並行插入可能導致間隙鎖競爭。另一個熱點可能是AUTO_INCREMENT
鎖機制;如果遇到這個問題,則可能需要重新考慮設計表或者應用,或者更改innodb_autoinc_lock_mode
設定。
MySQL允許在相同列上建立多個索引,無論是有意的還是無意的。MySQL需要單獨維護重複索引,並且優化器在優化查詢的時候也需要逐個的進行考慮,這會影響效能。
重複索引指的是在相同的列上按照相同的順序建立的相同型別的索引。應該避免這樣建立重複索引,發現後也應該立即移除
如果索引型別不同,不算是重複索引。比如KEY和FULLTEXT KEY