复合索引与索引跳跃扫描的关系及多条件下索引调用咨询
一、复合索引与索引跳跃扫描的关系
复合索引是将多列组合创建的索引,数据会按索引列的顺序依次排序。索引跳跃扫描是仅依赖复合索引才能实现的索引访问方式:当查询未使用复合索引的前导列(最左侧列)时,数据库会跳过前导列的所有不同取值,在每个前导列值对应的索引子树中,直接扫描后续列以匹配查询条件。
举个直观例子:假设存在复合索引(a,b,c),查询条件为b='test',数据库会先遍历a的所有不同值(如a=1、a=2、a=3...),然后在每个a对应的索引分支里查找b='test'的条目——这就是“跳跃”扫描,跳过前导列的分组,直接在后续列定位目标。
二、复合索引(eid, ename, esal)的调用场景分析
先给出测试用的emp表数据:
| eid | ename | esal |
|---|---|---|
| 10 | Raj | 5000 |
| 10 | Sam | 6000 |
| 10 | Raj | 1000 |
| 20 | Raj | 7000 |
| 30 | Tom | 8000 |
1. 仅指定eid=10:select * from emp where eid=10;
索引会被调用。复合索引的前导列是eid,查询条件完全匹配前导列,数据库可以直接定位到所有eid=10的连续索引条目(因为索引按eid排序,同值条目是连续的),通过索引快速找到对应行(聚簇索引直接取数据,非聚簇索引则回表获取完整行)。最终会返回测试数据中的前3行。
2. 指定eid=10和ename='Raj':select * from emp where eid=10 and ename='Raj';
索引会被调用。查询条件覆盖了复合索引的前两列(eid, ename),索引按eid排序后再按ename排序,所以在eid=10的子集中,ename='Raj'的条目也是连续的,数据库能精准定位到这些条目,比单条件查询范围更小、效率更高。最终返回测试数据中的第1、3行。
3. 条件顺序不同:select * from emp where esal=1000 and eid=10;
索引会被调用。SQL的WHERE条件顺序不影响数据库优化器的判断,优化器会自动调整条件顺序,优先使用复合索引的前导列eid=10缩小范围,再在这个子集中筛选esal=1000的条目。最终返回测试数据中的第3行。
4. 条件顺序完全反转:select * from emp where esal=1000 and ename='Raj' and eid=10;
索引会被调用。和上一场景同理,优化器会重新排序条件优先级,先通过eid=10定位大的范围,再用ename='Raj'进一步缩小,最后匹配esal=1000精准找到目标行。最终返回测试数据中的第3行。
内容的提问来源于stack exchange,提问作者stackoverflowquestion54 develo

