当前位置: 首页 > article >正文

索引的前导列

在 Oracle 数据库中,索引的前导列(Leading Column) 是复合索引(Composite Index)中的第一列。前导列的选择和使用对索引的性能和查询优化至关重要。以下是关于索引前导列的详细说明及其相关问题。


1. 什么是索引的前导列?

  • 复合索引:复合索引是由多个列组成的索引,例如 (a, b, c)

  • 前导列:复合索引中的第一列称为前导列。例如,在索引 (a, b, c) 中,a 是前导列。

  • 非前导列:复合索引中的其他列(如 b 和 c)称为非前导列。


2. 前导列的作用

  • 索引访问的起点

    • Oracle 在使用复合索引时,只能从前导列开始访问索引。如果查询条件中没有使用前导列,索引可能无法被使用。

  • 索引选择性

    • 前导列的选择性(即不同值的数量)直接影响索引的效率。选择性高的列(如主键或唯一列)作为前导列时,索引的效率更高。


3. 前导列的使用规则

  • 查询条件必须包含前导列

    • 如果查询条件中没有使用前导列,Oracle 无法使用复合索引。

    • 例如,对于索引 (a, b, c),查询 WHERE b = 1 AND c = 2 无法使用该索引,因为前导列 a 未在查询条件中使用。

  • 前导列的选择性

    • 如果前导列的选择性较低(例如性别列,只有“男”和“女”两个值),索引的效率可能较低。

    • 如果前导列的选择性较高(例如主键列),索引的效率较高。


4. 前导列的常见问题

问题 1:查询条件未使用前导列
  • 现象

    • 查询条件中未使用前导列,导致索引无法被使用。

  • 示例

    sql

    复制

    CREATE INDEX idx_a_b ON test(a, b);
    SELECT * FROM test WHERE b = 1;
    • 由于查询条件中未使用前导列 a,索引 idx_a_b 无法被使用。

  • 解决方案

    • 调整查询条件,包含前导列。

    • 例如:

      sql

      复制

      SELECT * FROM test WHERE a = 1 AND b = 1;
问题 2:前导列选择性较低
  • 现象

    • 前导列的选择性较低,导致索引效率低下。

  • 示例

    sql

    复制

    CREATE INDEX idx_gender_age ON employees(gender, age);
    SELECT * FROM employees WHERE gender = '男' AND age > 30;
    • 如果 gender 列的选择性较低(只有“男”和“女”两个值),索引 idx_gender_age 的效率可能较低。

  • 解决方案

    • 将选择性较高的列作为前导列。

    • 例如:

      sql

      复制

      CREATE INDEX idx_age_gender ON employees(age, gender);
问题 3:索引跳跃扫描(Index Skip Scan)
  • 现象

    • 当查询条件中未使用前导列时,Oracle 可能会使用索引跳跃扫描(Index Skip Scan)来访问非前导列。

  • 示例

    sql

    复制

    CREATE INDEX idx_a_b ON test(a, b);
    SELECT * FROM test WHERE b = 1;
    • Oracle 可能会使用索引跳跃扫描来访问 b = 1 的数据。

  • 解决方案

    • 如果索引跳跃扫描的性能不理想,可以考虑创建单列索引或调整复合索引的列顺序。

    • 例如:

      sql

      复制

      CREATE INDEX idx_b ON test(b);

5. 如何优化前导列的使用

1. 创建合适的索引
  • 根据查询模式创建合适的复合索引,确保前导列的选择性较高。

  • 例如:

    sql

    复制

    CREATE INDEX idx_a_b ON test(a, b);
2. 调整查询条件
  • 确保查询条件中包含前导列。

  • 例如:

    sql

    复制

    SELECT * FROM test WHERE a = 1 AND b = 1;
3. 使用提示(Hints)
  • 如果优化器未选择索引,可以使用提示强制使用索引。

  • 例如:

    sql

    复制

    SELECT /*+ INDEX(test idx_a_b) */ * FROM test WHERE a = 1 AND b = 1;
4. 更新统计信息
  • 确保表和索引的统计信息是最新的,以便优化器生成最佳的执行计划。

  • 例如:

    sql

    复制

    EXEC DBMS_STATS.GATHER_TABLE_STATS('SCHEMA_NAME', 'TEST');
5. 分析执行计划
  • 使用 EXPLAIN PLAN 或 SQL*Plus 的 AUTOTRACE 功能分析查询的执行计划。

  • 例如:

    sql

    复制

    EXPLAIN PLAN FOR
    SELECT * FROM test WHERE a = 1 AND b = 1;
    SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);

6. 示例分析

示例 1:前导列选择性高
  • 表结构

    sql

    复制

    CREATE TABLE test (
        id NUMBER,
        a NUMBER,
        b NUMBER
    );
    
    CREATE INDEX idx_a_b ON test(a, b);
  • 查询

    sql

    复制

    SELECT * FROM test WHERE a = 1 AND b = 1;
  • 执行计划

    plaintext

    复制

    ------------------------------------------------------------------------------------
    | Id  | Operation                   | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
    ------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT            |         |    10 |   200 |     3   (0)| 00:00:01 |
    |*  1 |  TABLE ACCESS BY INDEX ROWID| TEST    |    10 |   200 |     3   (0)| 00:00:01 |
    |*  2 |   INDEX RANGE SCAN          | IDX_A_B |    10 |       |     2   (0)| 00:00:01 |
    ------------------------------------------------------------------------------------
    • INDEX RANGE SCAN:使用索引 IDX_A_B 查找 a = 1 且 b = 1 的行。

示例 2:前导列选择性低
  • 表结构

    sql

    复制

    CREATE TABLE employees (
        id NUMBER,
        gender VARCHAR2(10),
        age NUMBER
    );
    
    CREATE INDEX idx_gender_age ON employees(gender, age);
  • 查询

    sql

    复制

    SELECT * FROM employees WHERE gender = '男' AND age > 30;
  • 执行计划

    plaintext

    复制

    ------------------------------------------------------------------------------------
    | Id  | Operation                   | Name           | Rows  | Bytes | Cost (%CPU)| Time     |
    ------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT            |                |    10 |   200 |     3   (0)| 00:00:01 |
    |*  1 |  TABLE ACCESS BY INDEX ROWID| EMPLOYEES      |    10 |   200 |     3   (0)| 00:00:01 |
    |*  2 |   INDEX RANGE SCAN          | IDX_GENDER_AGE |    10 |       |     2   (0)| 00:00:01 |
    ------------------------------------------------------------------------------------
    • INDEX RANGE SCAN:使用索引 IDX_GENDER_AGE 查找 gender = '男' 且 age > 30 的行。


总结

  • 索引的前导列是复合索引中的第一列,对索引的使用和性能至关重要。

  • 确保查询条件中包含前导列,并根据查询模式创建合适的索引。

  • 通过更新统计信息、分析执行计划和使用提示,可以进一步优化查询性能。


http://www.kler.cn/a/595330.html

相关文章:

  • 【MySQL】第十五弹---全面解析事务:定义、起源、版本支持与提交方式
  • 智能体开发革命:灵燕平台如何重塑企业AI应用生态
  • OBOO鸥柏丨多媒体信息发布系统立式触摸屏一体机国产化升级上市
  • 智能施工方案生成工具开发实践:从架构设计到核心实现
  • 回溯法经典练习:组合总和的深度解析与实战
  • OpenHarmony 入门——ArkUI 跨页面数据同步和页面级UI状态存储LocalStorage小结(二)
  • 首页性能优化
  • 多条件排序(C# and Lua)
  • vscode设置console.log的快捷输出方式
  • springboot项目引用外部jar包,linux部署后启动失败,找不到jar包
  • LeetCode[454]四数相加Ⅱ
  • 分布式唯一ID
  • LDAP从入门到实战:环境部署与配置指南(下)
  • 希尔排序中的Hibbard序列
  • 如何在MCU工程中启用HardFault硬错误中断
  • FPGA中串行执行方式之状态机
  • 蓝桥杯 之 数论
  • Spring Boot 集成 Quartz 实现定时任务(Cron 表达式示例)
  • Windows10配置OpenJDK11
  • 基于深度学习的目标追踪技术全解析