MySql - 索引

索引長度

索引長度短,區分度就低,索引長度長,區分度高,查詢效率高,可是索引要佔內存,因此要找到一個平衡點;sql

舉個例子: (張,張三,張三哥),若是索引長度取1的話,那麼每一行的索引都是 張 這個字,徹底沒有區分度,結果這樣三行徹底是隨機排的,由於索引都同樣;若是長度取2,那麼排序的時候至少前兩個是排對了的,若是取3,區分度達到100%,已經提早排序;數據庫

有一些特殊的字段好比url,絕大部分的url都是 http://www. 開頭的,這種狀況下索引長度取取到11都是無效的,須要更長的索引,那麼有沒有優雅的方式來解決呢;
第一種方法: 能夠將數據倒序存入數據庫;
第二種方法:對字符串進行crc32哈希處理;app

創建索引

在多個Where條件的時候,會優先採用rows最少的索引。若是多個Where條件查詢很頻繁,則將where中全部字段加到聯合索引。
注意:函數

  • 數據區分度低的不該創建索引,好比sex就0、1,即區分50%。通常若rows大於總數據條數20%,則數據庫走全表掃描。
  • 若是該表大部分是單條查詢,則應使用hash索引,由於B-Tree索引時間複雜度O(log(n)),Hash索引爲O(1)。
  • where子句的查詢條件裏有 != ,索引將無效。能夠優化爲in(xx, xx)
  • where子句使用了sql函數的時候,索引將無效,好比:select * from tb where YEAR(data) < '2017'; 可優化爲 data < CURDATE()
  • LIKE查詢必須是前綴固定的,不然沒法使用索引。如:Title%可使用索引,%Title和%Title%不能使用索引。
  • 索引列儘可能避免NULL,應該指定列爲NOT
    NULL或設置默認值。在MySQL中,含有NULL值的列很難進行查詢優化,由於它們使得索引、索引的統計信息以及比較運算更加複雜。索引不存Null值,因此會致使 SELECT * FROM tb WHERE name != 'xxx' 不會返回name爲Null的數據。
  • 對於複合索引(key1, key2),select * from tb where key1 = xxx and key2 = xxxselect * from tb where key1 = xxx 會走複合索引,而 select * from tb where key2 = xxx 不會走複合索引。即最左前綴匹配。
  • 當你須要在一篇大的文章中搜索一個詞時,如: 「WHERE content LIKE
    ‘%apple%’」,索引是沒有意義的,這須要全文索引。InnoDB引擎對FULLTEXT索引的支持是MySQL5.6新引入的特性,可對CHAR、VARCHAR、TEXT類型的列建立全文索引,全文搜索的語法:MATCH(col1,col2,…) AGAINST (expr[search_modifier]),默認狀況下全文搜索大小寫不敏感。
  • 不要觸發強制類型掃描,好比 select * from tb where phone = 18812345678,其中phone爲varchar,這不會走索引。
  • 在col_1和col_2上創建索引,不要select * from tb col_1=2 or col_2=2,應優化爲select * from tb where col_1=2 union select * from tb where col_2=2

索引覆蓋(複合索引)

對於select key_1  from t where key_2 ·····;這樣的查詢,查詢的處理過程爲:首先去檢索key_2索引找到主鍵id,而後根據主鍵id去檢索正確的數據行。這樣就是兩次檢索。
將key_1和key_2加到聯合索引,InnoDB能夠直接在索引中獲取結果數據集,這就是索引覆蓋。優化

如下狀況,InnoDB沒法覆蓋查詢:
1 select選擇的字段中含有不在索引中的字段 ,也即索引沒有覆蓋所有的列。
2 where 條件中不能含有對索引進行like的操做。url

Join的列索引化

若是應用程序有不少 JOIN 查詢,你應該確認兩個表中Join的字段是被建過索引的。這樣,MySQL內部會啓動爲你優化Join的SQL語句的機制。Join的字段,應該是相同的類型的,對於STRING類型,還須要有相同的字符集才行。(兩個表的字符集有可能不同)code

相關文章
相關標籤/搜索