You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL 5.7.32中指定SQL为何未使用索引条件下推(ICP)?

问题分析:为何未触发索引条件下推(ICP)

表结构定义

CREATE TABLE `user_cp` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `cp_id` varchar(25) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT 'cpId 下划线分割',
  `intimacy` int(11) NOT NULL COMMENT '加了add_exp后的当前等级下的经验',
  `attenuation_utime` int(11) NOT NULL DEFAULT '0' COMMENT '扣减时间',
  `utime` int(11) NOT NULL COMMENT '更新时间',
  `ctime` int(11) NOT NULL COMMENT '时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `cp_id_unique` (`cp_id`),
  KEY `idx_attenuationutime_utime_intimacy_cpid` (`attenuation_utime`,`utime`,`intimacy`,`cp_id`)
) ENGINE=InnoDB AUTO_INCREMENT=31988443 DEFAULT CHARSET=utf8

查询SQL

EXPLAIN SELECT cp_id
FROM user_cp
WHERE utime < 1707912100
 AND attenuation_utime < 1708430500
 AND intimacy > 0

执行环境

MySQL Server版本:5.7.32


未触发ICP的原因分析

原因1:优化器选择全表扫描而非索引扫描

索引条件下推(ICP)仅在使用二级索引扫描时生效。若MySQL优化器评估后认为全表扫描代价更低(例如满足attenuation_utime < 1708430500的行数占表数据量比例极高,索引扫描的IO成本反而高于全表扫描),会直接选择全表扫描,此时ICP自然不会被触发。

原因2:联合索引结构与查询条件的组合限制ICP触发

当前使用的联合索引列顺序为attenuation_utime → utime → intimacy → cp_id,而查询条件存在以下特征:

  • attenuation_utime < 1708430500是范围条件,作为索引首列,优化器只能扫描所有满足该范围的索引条目;
  • 后续的utime < 1707912100和intimacy > 0同样是范围条件,无法利用索引有序性进一步缩小扫描范围。

在MySQL 5.7中,ICP更倾向于触发在前缀列为等值匹配(=、IN),后续列存在过滤条件的场景。当前缀列和后续列均为范围条件时,优化器会认为ICP带来的性能收益有限,因此不启用该优化。

验证建议

  1. 查看EXPLAIN结果的type列:若为ALL则是全表扫描,ICP不生效;若为range则是索引范围扫描,需进一步检查Extra列是否包含Using index condition。
  2. 强制使用目标索引(FORCE INDEX(idx_attenuationutime_utime_intimacy_cpid))后执行EXPLAIN,观察是否触发ICP。

内容的提问来源于stack exchange,提问作者panici

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 16:12:32