發生場景
在查詢學生表的時候,需要支持根據創建時間來篩選出某段時間內入學的學生總數,因此在創建時間上加了索引,但是最終發現還是會走全量查詢。
實驗過程
1
2
3
4
5
6
7
|
CREATE TABLE `t_user` ( `id` bigint (11) unsigned NOT NULL COMMENT '學生id' , ` name ` varchar (24) NOT NULL COMMENT '學生名稱' , `createTime` dat NOT NULL COMMENT '創建時間' , PRIMARY KEY (`id`), KEY `index_updateTime` (`createTime`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 |
1
|
select count (1) from t_user where createTime between '2022-08-30' and '2022-08-31' ; |
使用insert語句插入3萬多條數據後,其中30號至31號之前有9千多條數據,發現查詢的時候並沒有走到索引。
結果如下:
縮小查詢區間,只查31號的(4千多條數據),卻發現可以走到索引了,
結果如下:
1
|
select count (1) from t_user where createTime between '2022-08-31' and '2022-08-31' ; |
再找一個數據量爲5千的區間來試一下,也是會走到索引的,
結果如下:
1
|
select count (1) from t_user where createTime between '2022-08-23' and '2022-08-25' ; |
沒走到索引是因爲between…and引起的嗎?如果改爲>=和<=呢。
結果如下:
1
|
select count (1) from t_user where createTime >= '2022-08-30' and createTime <= '2022-08-31' ; |
結論
經過實驗發現,當查詢的數據量達到6千(佔比20%左右),就不走索引了。
引起原因:
表的數據量太大,會讓數據庫中的優化器進行處理。
優化器是在表裏面有多個索引的時候,決定使用哪個索引,查詢的量太大,導致優化器認爲走全表查詢時間效率更佳。
但是如果一定要用到區間查詢,這個問題該如何解決呢?
方案一
1
|
select count (1) from t_user where createTime between '2022-08-30' and '2022-08-31' limit 1; |
方案二
1
|
select count (1) from t_user FORCE INDEX (index_updateTime) where createTime between '2022-08-30' and '2022-08-31' ; |
思考:
當查詢數據量達到一定量的時候會導致between…and索引失效,那分頁查詢的時候呢?
1
|
select id, name , createTime from t_user where createTime between '2022-08-30' and '2022-08-31' limit 1,500; |
可見,查詢第一頁的時候索引有效,但是隨着頁碼越來越大的時候,索引卻失效了,
1
|
select id, name , createTime from t_user where createTime between '2022-08-30' and '2022-08-31' limit 100000,500; |
因此,遇到這種因查詢數據量過大而導致的索引失效的問題,需要對其功能做相應限制處理
轉自
Mysql中between...and引起的索引失效問題及解決_Mysql_腳本之家
https://www.jb51.net/database/293553brm.htm