神奇了,當(dāng) MySQL l查詢條件為“>=”時(shí),竟然不走索引?
我們都知道在數(shù)據(jù)庫查詢時(shí),索引可以極大地提高查詢效率。通常在使用的時(shí)候,都會(huì)針對(duì)頻繁查詢的關(guān)鍵字段建立索引。
比如,當(dāng)以交易日期(trans_date)來查詢交易記錄時(shí),通常會(huì)對(duì)該字段添加索引,以便在大量數(shù)據(jù)的情況下提升查詢效率。
針對(duì)trans_date字段,創(chuàng)建union_idx_query索引,那么在下面以trans_date為查詢條件的語句中,毫無疑問是會(huì)走索引的:
select count(1) from A; // 40000
EXPLAIN select * from A where trans_date = '20220222';
索引1
此時(shí),我們會(huì)想當(dāng)然地以為,只要?jiǎng)?chuàng)建了索引,其他情況的使用同樣會(huì)走索引。比如下面的查詢語句:
select count(1) from t_trans_log_info where trans_date > '20220122'; //11200
EXPLAIN select * from t_trans_log_info where trans_date > '20220122';
上面的查詢語句使用了”>“來進(jìn)行范圍的查詢,而且trans_date字段同樣創(chuàng)建了索引,那么上述SQL語句是否會(huì)走索引呢?答案是不一定。
索引2
explain上述SQL語句,發(fā)現(xiàn)的確走了索引。
但當(dāng)換一個(gè)查詢參數(shù)時(shí):
select count(1) from t_trans_log_info where trans_date > '20220222'; //1120
EXPLAIN select * from t_trans_log_info where trans_date > '20120222';
explain的結(jié)果顯示沒有走索引,而是進(jìn)行了全表掃描:
索引3
為什么同樣的查詢語句,只是查詢的參數(shù)值不同,卻會(huì)出現(xiàn)一個(gè)走索引,一個(gè)不走索引的情況呢?
答案很簡(jiǎn)單:上述索引失效是因?yàn)镈BMS發(fā)現(xiàn)全表掃描比走索引效率更高,因此就放棄了走索引。
也就是說,當(dāng)Mysql發(fā)現(xiàn)通過索引掃描的行記錄數(shù)超過全表的10%-30%時(shí),優(yōu)化器可能會(huì)放棄走索引,自動(dòng)變成全表掃描。某些場(chǎng)景下即便強(qiáng)制SQL語句走索引,也同樣會(huì)失效。
類似的問題,在進(jìn)行范圍查詢(比如>、< 、>=、<=、in等條件)時(shí)往往會(huì)出現(xiàn)上述情況,而上面提到的臨界值根據(jù)場(chǎng)景不同也會(huì)有所不同。
所以,如果你在項(xiàng)目中采用了上述方式的查詢,又希望它能夠走索引,就需要特別注意了。通常需要添加一些其他的限制條件或用其他方式來保證索引的有效性。