MySQL索引的探索

Cardinality

image.png
Cardinality數值表示了該索引字段的重複率程度,數值越大表明重複率越低,PRIMIARY是自增的,可以保證插入/更新數據按照磁盤順序進行,可是id字段由於沒有什麼可篩選的含義,不能進行篩選查詢。sql

咱們爲data_unique_key創建了一個惟一索引,這個屬性的值是一些篩選字段的md5值,若是是具體查詢某一條數據的話,能夠md5後查詢data_unique_key爲該值,速度很快。緩存

對於重複率很是大的字段,探索一下爲a創建索引是否有必要。
a的Cardinality是21
b的Cardinality是77
c的Cardinality是1305優化

最左匹配原則

ALTER TABLE test ADD INDEX index (a, b, c);

假設如今有一張test表,咱們先創建一個聯合索引,索引包含a,b,c3個字段。
image.png
咱們創建的索引是3個字段聯合的,可是查詢的時候只用兩個字段進行篩選,也會使用這個索引的前兩個字段進行篩選。
image.png
仍是使用兩個字段進行篩選,只是用了c而不是b,查詢使用了index這個索引可是key_len是202,說明只用了a的索引部分。這現象是「最左匹配原則」帶來的。也就是說要像最大化利用索引,篩選的時候要根據創建索引的字段順序就行查詢,若是where等篩選/分組/排序操做能命中索引的部分順序字段,則也會使用這部分順序字段進行索引。
image.png
SELECT中有索引的字段,優化器會選擇使用索引查詢,因此查詢出來的結果是以page_name排序的。
反之,若是SELECT中沒有索引字段,或者只有部分包含,或者是查詢 * ,都不會使用索引進行查詢spa

a是否有必要成爲索引字段

SELECT a, e FROM test WHERE a = '2';
image.png
(這個時間應該是利用了緩存的基礎上的時間,第一次進行全表查詢的時間是7秒多,一樣的sql再次查詢就變成了1+秒,試過將query_cache_type和query_cache_size都設置爲0,仍是這樣,有說法是操做系統級別的緩存是沒法限制的。若是一開始就創建索引,並SELECT a FROM test,也是六七秒,因此懷疑查詢後都會有緩存,那麼如下的時間都是在這個基礎上進行截圖)操作系統

創建一個聯合索引3d

ALTER TABLE test ADD INDEX index(`a, b, c`);
-- SQL1:
SELECT a, e  FROM test WHERE a = '1' ;

image.png

-- SQL2:
SELECT a, e FROM test WHERE a = '1' AND b = 2;

image.png

-- SQL3:
SELECT a, e FROM test WHERE a = '1' AND data_type = 2 AND c = 'math';

發現了只利用索引的一個字段進行查詢,查詢花費的時間比全表查詢還要慢不少,可是索引字段利用率大,查詢花費的時間就不多了。code

刪除上面創建的索引,再創建一個不包含a的索引blog

ALTER TABLE test
DROP INDEX index,
ADD INDEX index(b, c);

SQL1的執行以下:
image.png
至關於查詢type是all,耗時比以前的包含a索引的快
image.png
image.png
一樣的SQL2,能夠看到索引利用長度是1,可是速度是幾乎同樣的,這裏能夠看出來a的重複率過高,是索引這個字段的意義並不大,並且會增長索引key的長度,帶來B+Tree每個節點的鍵值存儲量減小,樹的結構可能會更深,進而查詢更慢。排序

總結:索引

  • 聯合索引中每個索引表明的權重是不同的,好比索引(a, b, c),a是百,b是十,c是個位,那麼假設篩選條件是b和c,根據B+Tree結構,索引獲得的最終是分散的,因此使用索引的意義就不大,天然就不會使用索引了
  • 創建的索引字段須要充分利用,不恰當的使用可能會比全表查詢來的更慢
  • 爲Cardinality很小的字段創建索引的必要性有待商榷,通常狀況下重複率很大的字段不須要創建索引。

(以上截圖都模糊掉自身數據,用a,b,c來代替)

相關文章
相關標籤/搜索