现象
SQL报警慢查询
原SQL
select * from `awards_record` WHERE ( `create_time` between '2024-07-01 00:00:00' and '2024-07-30 00:18:58.004')
索引信息
KEY `idx_createtime` (`create_time`) USING BTREE
explain分析,发现没走上面的索引
原因
查询数据时,如果走普通索引,那么会产生回表操作,因为普通索引属于非聚集索引,叶子节点存放的是主键字段的值,拿到主键字段后再去表中根据主键值找到对应的记录。
因此,当数据量很大,而查询数据也很大时,考虑到回表的消耗,就不走索引;
当数据量很大,而查询数据很小,这个时候比起全表扫描,回表的消耗相对少,所以走索引。
调试
缩短查询范围,把从1号开始查改到13号开始查
select * from `awards_record` WHERE ( `create_time` between '2024-07-13 00:00:00' and '2024-07-30 00:18:58.004')
explain分析
结果对比
数据量只差了六千左右,效率却差了一个数量级
select * from `awards_record` WHERE ( `create_time` between '2024-07-13 00:00:00' and '2024-07-30 00:18:58.004') \G;
select * from `awards_record` WHERE ( `create_time` between '2024-07-12 00:00:00' and '2024-07-30 00:18:58.004') \G;
结论
当筛选结果占比总数据量很高的时候因为需要回表,所以优化引擎会选择不走索引,当筛选结果占比较小的时候会走索引。
我当前的数据量是8%时走了索引,9.3%时没走索引
备注
我的业务场景是:
每分钟推送的时候会同时吧本月未能及时推送的内容重新推送,理论上不应该存在很久都没推送的内容,所以把重新推送的筛选时间缩短到一周甚至一天也是没问题的。
各位同学根据自身业务场景选择具体优化方案