外观
联合索引 A= 10 B > 100 C > 50 这种怎么查?
⭐ 题目日期:
字节 - 2024/9/3
📝 题解:
在联合索引 (A, B, C) 的场景下,针对查询条件 A=10 AND B>100 AND C>50,数据库的查询流程和索引使用情况如下:
一、索引使用分析
- 最左前缀原则:
A=10是等值查询,联合索引的第一列被完全命中,索引可高效定位到所有A=10的连续数据块。B>100是范围查询,索引的第二列B部分生效(仅定位到B>100的起始位置)。C>50无法利用索引,因为B的范围查询导致后续索引列 (C) 的有序性被破坏,数据库需在结果集中逐行过滤C>50的条件。
- 索引扫描范围:
- 数据库会扫描联合索引中
A=10且B>100的所有记录,然后对这些记录的C字段进行过滤。
- 数据库会扫描联合索引中
二、查询执行流程
- 索引定位:
- 在联合索引树中,快速定位到
A=10的起始位置。 - 在
A=10的范围内,找到B>100的最小值,开始顺序扫描。
- 在联合索引树中,快速定位到
- 数据过滤:
- 对满足
A=10 AND B>100的每一行,检查C>50是否成立。 - 符合条件的行将被返回或进一步处理(如
JOIN、聚合等)。
- 对满足
- 终止条件:
- 当扫描到
A≠10或B≤100时停止(因索引按(A, B, C)排序)。
- 当扫描到
三、执行计划示例(EXPLAIN 输出)
EXPLAIN SELECT * FROM table WHERE A=10 AND B>100 AND C>50;可能的输出结果:

四、优化建议
1. 调整索引顺序
- 问题:原索引
(A, B, C)无法有效覆盖C的条件。 - 改进:若查询中
C是高频过滤条件,可尝试将等值列前置,范围列后置:
-- 假设 C 是等值查询(如 C=50),但本例中 C 是范围,无法直接优化
CREATE INDEX idx_A_C_B ON table(A, C, B);2. 使用覆盖索引(Covering Index)
- 方法:将查询所需的字段全部包含在索引中,避免回表。
CREATE INDEX idx_A_B_C_covering ON table(A, B, C) INCLUDE (other_columns);3. 索引条件下推(Index Condition Pushdown, ICP**)**
- 优化原理:在存储引擎层提前过滤
C>50,减少回表次数。 - 要求:数据库支持 ICP(如 MySQL 5.6+ 的 InnoDB)。
- 效果:
Extra列显示Using index condition。
4. 分页查询优化
- 场景:若需分页(如
LIMIT 1000, 10),避免深分页:
-- 通过子查询或游标优化
SELECT * FROM table
WHERE A=10 AND B>100 AND C>50 AND id > last_id
ORDER BY id LIMIT 10;五、总结
- 索引生效范围:联合索引
(A, B, C)中,A=10和B>100可触发索引范围扫描,但C>50需逐行过滤。 - 优化方向:
- 调整索引顺序(需结合查询模式)。
- 利用覆盖索引减少回表开销。
- 启用索引条件下推(ICP)提前过滤。
- 执行代价:扫描行数取决于
A=10 AND B>100的数据量,需监控rows字段并控制结果集规模。
