常見情況:1、使用函數(shù)或運(yùn)算;2、隱式類型轉(zhuǎn)換;3、使用不等于(!=或);4、使用like操作符,并以通配符開頭;5、or條件;6、null值;7、索引選擇性低;8、復(fù)合索引的最左前綴原則;9、優(yōu)化器決策;10、force index和ignore index。
MySQL中的索引是幫助優(yōu)化查詢性能的重要工具,但在某些情況下,索引可能不會(huì)如預(yù)期地工作,即索引“失效”。
以下是導(dǎo)致MySQL索引失效的一些常見情況:
:當(dāng)在索引列上使用函數(shù)或進(jìn)行運(yùn)算時(shí),索引通常不會(huì)生效。例如:
SELECT?*?FROM?users?WHERE?YEAR(date_column)?=?2023;
登錄后復(fù)制
這里,YEAR(date_column)?使得索引失效。
2.?隱式類型轉(zhuǎn)換:當(dāng)查詢條件中涉及隱式類型轉(zhuǎn)換時(shí),索引可能不會(huì)被使用。例如,如果一個(gè)列是字符串類型但查詢時(shí)使用了數(shù)字,或者反之。
SELECT?*?FROM?users?WHERE?id?=?'123';??--?假設(shè)id是整數(shù)類型
登錄后復(fù)制
使用不等于(!=或):使用不等于操作符通常會(huì)導(dǎo)致索引失效,因?yàn)樗枰獟呙杷饕亩鄠€(gè)值。
SELECT?*?FROM?users?WHERE?age?!=?25;
登錄后復(fù)制
使用LIKE操作符,并以通配符開頭:當(dāng)使用LIKE操作符且模式以通配符%開頭時(shí),索引通常不會(huì)生效。
SELECT?*?FROM?users?WHERE?name?LIKE?'%Smith%';
登錄后復(fù)制
OR條件:使用OR條件時(shí),如果涉及的列沒有都被索引,或者其中一個(gè)條件導(dǎo)致了索引失效,那么整個(gè)查詢可能都不會(huì)使用索引。
SELECT?*?FROM?users?WHERE?age?=?25?OR?name?=?'John';
登錄后復(fù)制
NULL值:如果索引列包含NULL值,并且查詢條件涉及到NULL,索引可能不會(huì)生效。
SELECT?*?FROM?users?WHERE?age?IS?NULL;
登錄后復(fù)制
-
索引選擇性低:如果索引列中的值重復(fù)度很高(例如性別列只有“男”和“女”兩個(gè)值),則索引可能不會(huì)被使用,因?yàn)槿頀呙杩赡芨鼮楦咝А?br />
復(fù)合索引的最左前綴原則:對(duì)于復(fù)合索引,查詢條件必須滿足最左前綴原則,否則索引可能不會(huì)生效。例如,如果有一個(gè)(a, b, c)的復(fù)合索引,那么只有a、(a, b)和(a, b, c)的組合才能充分利用索引。
優(yōu)化器決策:MySQL的查詢優(yōu)化器可能會(huì)基于統(tǒng)計(jì)信息和其他因素決定不使用索引,即使索引是存在的。這通常發(fā)生在它認(rèn)為全表掃描比使用索引更快時(shí)。
FORCE INDEX和IGNORE INDEX:使用FORCE INDEX可以強(qiáng)制查詢使用某個(gè)索引,而IGNORE INDEX則告訴優(yōu)化器忽略某個(gè)索引。如果誤用這些提示,可能會(huì)導(dǎo)致索引失效。
為了避免索引失效,建議:
-
仔細(xì)設(shè)計(jì)和選擇索引列。
定期檢查查詢的性能,并考慮對(duì)查詢進(jìn)行優(yōu)化。
使用EXPLAIN命令來(lái)查看查詢的執(zhí)行計(jì)劃,并確定是否使用了索引。
監(jiān)控?cái)?shù)據(jù)庫(kù)的性能,并定期更新統(tǒng)計(jì)信息。
考慮使用覆蓋索引(Covering Index)來(lái)提高查詢性能。