MySql - 索引
索引長度
索引長度短,區分度就低,索引長度長,區分度高,查詢效率高,但是索引要占內存,所以要找到一個平衡點;
舉個例子: (張,張三,張三哥),如果索引長度取1的話,那么每一行的索引都是 張 這個字,完全沒有區分度,結果這樣三行完全是隨機排的,因為索引都一樣;如果長度取2,那么排序的時候至少前兩個是排對了的,如果取3,區分度達到100%,已經提前排序;
有一些特殊的字段比如url,絕大部分的url都是 http://www. 開頭的,這種情況下索引長度取取到11都是無效的,需要更長的索引,那么有沒有優雅的方式來解決呢;
第一種方法: 可以將數據倒序存入數據庫;
第二種方法:對字符串進行crc32哈希處理;
建立索引
在多個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 = xxx 或 select * 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的操作。
Join的列索引化
如果應用程序有很多 JOIN 查詢,你應該確認兩個表中Join的字段是被建過索引的。這樣,MySQL內部會啟動為你優化Join的SQL語句的機制。Join的字段,應該是相同的類型的,對于STRING類型,還需要有相同的字符集才行。(兩個表的字符集有可能不一樣)
總結
以上是生活随笔為你收集整理的MySql - 索引的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用MediaPlayer做个带进度条可后
- 下一篇: jquery 轮播插件 bxslider