開發中可能會遇到索引失效的狀況,使用到了索引字段可是卻沒有利用索引查詢。mysql
創建一個測試用表sql
DROP TABLE IF EXISTS index_test; CREATE TABLE index_test( t_id INT PRIMARY KEY, key1 INT, key2 INT, key3 INT, key4 INT, content VARCHAR(20) ); INSERT INTO index_test VALUES(1,1,1,1,1,'a'); INSERT INTO index_test VALUES(2,1,2,3,4,'b'); INSERT INTO index_test VALUES(3,4,1,2,3,'c'); INSERT INTO index_test VALUES(4,3,4,1,2,'d'); INSERT INTO index_test VALUES(5,2,3,4,1,'e'); CREATE INDEX index_key1_key2_key3_key4 ON index_test(key1,key2,key3,key4);
如何防止索引失效:函數
1. 最佳左前綴法則: 索引爲多列時,查詢條件最好從索引最左邊開始,不跳過中間列。(不過能夠插入別的條件,好比key=1,content = ‘a’, key2 = 2 這樣,不會影響總體效率)測試
使用的是查詢類型是ref(索引掃描),根據索引進行了常量查詢(索引的取值是個常數),查詢結果利用率是100%(只掃了符合條件的那一條數據)。優化
當使用的查詢條件沒有從索引的第一列開始時,查詢類型變成了all(掃描全表),key = null (沒有用到索引),ref = null(沒有利用索引查詢), 查詢結果利用率只有20%(掃描了5行數據,只有一條符合條件。)spa
2. 不要在索引列上作任何操做(計算,函數,類型轉換,不等於,is null, is not null)3d
把key = 1 變成了 key +1 = 2 結果同樣,可是查詢從索引查詢變成了全表掃描。code
3. 範圍查詢右邊的索引會失效。 blog
此時是一個範圍查詢,並且效率很高。索引
當key2 後面 加了 key3後,雖然條件更加精確了,可是效率反而低了。 由於key3的索引沒有被使用,單獨爲key3進行了全表掃描。
因此這時最好創建索引順序 key1,key3,key2, 而後把範圍查詢放在最後。
4. 儘可能使用索引覆蓋, 少用 select * 查詢
查詢內容中有不是索引的列(我這個表裏的content不是索引),則mysql會先找到符合條件的行,而後從表中讀取數據
查詢的列所有是索引內的列(不是同一個索引裏的也能夠),則mysql會直接從索引中讀取數據。
5. 通配符不要做爲字段開頭,不然會致使索引失效(like '%aaa')
加一個key5用來測試
ALTER TABLE index_test ADD COLUMN key5 VARCHAR(20); UPDATE index_test SET key5 = CONCAT('test_',content,key1); CREATE INDEX index_key5 ON index_test(key5);
%放在後面,進行了索引key5的範圍搜索。
%放在前面,或者兩邊,進行了全表搜索
解決:在實際狀況中,不可避免會使用%在兩邊的狀況,這時能夠利用索引覆蓋提升效率
建立複合索引key1,key2,key5,這樣查詢內容變爲包含key5的一個索引中的內容,查詢索引覆蓋,變爲索引查詢
再加個 主鍵依然生效。 可是加其餘索引列就不能夠。
6. 新人殺手= =|| varchar字段沒加 ' ',大幅拖慢速度並且很難被發現。。。
正常狀況: 索引查詢, 使用了key5, 常數查詢。
好比有個‘2000’, 寫成了 2000, 則會索引失效。變成了全表搜索
7.儘可能不要用or。
聽說舊版本會致使索引失效,我試着沒問題,貌似如今沒事了= =?
這個通常是用union 或者 in 來優化。