添加恒真条件review_count>=0后MySQL查询性能提升10倍的原因咨询
store0_.review_count >= 0能让MySQL查询性能提升10倍? 你的核心问题出在MySQL查询优化器对联合索引的选择逻辑上,结合你提供的联合索引(review_count, store_id, status, name, address),具体原因拆解如下:
1. 恒真条件触发了联合索引的最左前缀匹配
你的联合索引最左列是review_count,在未添加review_count >= 0时,WHERE子句里没有直接引用这个列的过滤条件(仅ORDER BY用到),优化器会认为这个索引的最左前缀无法被WHERE条件利用,大概率会选择其他索引(比如status或name的单列索引),甚至走全表扫描。
而添加review_count >= 0这个恒真条件后,相当于给优化器一个明确的信号:可以利用联合索引的最左前缀列review_count。因为这个条件匹配所有行,优化器可以直接沿着这个索引的有序结构读取数据,完美匹配ORDER BY store0_.review_count的排序需求,彻底避免了额外的排序操作(Using filesort)——这是性能提升的关键之一。
2. 联合索引实现了覆盖查询,减少回表开销
你的联合索引中包含了status和name列,WHERE子句里的status='APPROVED'和name LIKE '가게%'可以直接在索引层面完成过滤,不需要回表查询store表的原始数据。同时,索引里还包含了查询需要的name、address列,进一步减少了IO操作的开销。
3. 执行计划从“筛选+排序+跳页”变为“索引有序扫描+直接跳页”
- 原查询的执行计划可能是:先通过单列索引筛选符合
status和name条件的数据,关联其他表后,再对结果集进行ORDER BY review_count排序,最后跳过8000行取100条。排序和大OFFSET跳页都会带来大量的CPU和内存消耗。 - 添加恒真条件后,执行计划切换为:直接遍历
(review_count, ...)联合索引,按review_count有序读取数据,同时在索引内过滤status和name条件,关联表后直接返回有序结果,OFFSET 8000可以通过索引指针快速定位,不需要先扫描并排序大量数据,这直接把处理量降到了最低。
4. 优化器的成本评估逻辑变化
MySQL优化器选择执行计划时,会综合评估扫描行数、是否需要排序、IO开销等成本。没有review_count >=0时,优化器无法明确感知到联合索引能同时满足过滤、排序、覆盖查询的多重需求,因此选择了成本更高的执行计划;添加条件后,优化器能清晰判断出这个联合索引的成本远低于其他方案,所以切换到了最优路径。
内容的提问来源于stack exchange,提问作者firefly_0

