【问题标题】:Oracle Index with multiple Columns querying on single column具有多列查询单列的 Oracle 索引
【发布时间】:2012-08-15 14:33:27
【问题描述】:

在我们安装的 Oracle 中的一个表中,我们有一个在其中两列(X 和 Y)上有索引的表。如果我用 where 子句只触及 X 列对表进行查询,Oracle 是否能够使用索引?

例如:

表 Y: 可乐, Col_B, Col_C,

索引存在于 (Col_A, Col_B)

SELECT * FROM Table_Y WHERE Col_A = 'STACKOVERFLOW';

会使用索引,还是会进行表扫描?

【问题讨论】:

    标签: oracle indexing


    【解决方案1】:

    视情况而定。

    您可以通过让 Oracle 解释执行计划来检查它:

    EXPLAIN PLAN FOR 
       SELECT * FROM Table_Y WHERE Col_A = 'STACKOVERFLOW';
    

    然后

    select * from table(dbms_xplan.display);
    

    所以,例如

    create table table_y (
      col_a varchar2(30),
      col_b varchar2(30),
      col_c varchar2(30)
    );
    
    create unique index table_y_ix on table_y (col_a, col_b);
    

    然后是一个

    explain plan for
      select * from table_y
      where col_a = 'STACKOVERFLOW';
    
    select * from table(dbms_xplan.display);
    

    计划(在我的安装中)如下所示:

    ------------------------------------------------------------------------------------------
    | Id  | Operation                   | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
    ------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT            |            |     1 |    51 |     1   (0)| 00:00:01 |
    |   1 |  TABLE ACCESS BY INDEX ROWID| TABLE_Y    |     1 |    51 |     1   (0)| 00:00:01 |
    |*  2 |   INDEX RANGE SCAN          | TABLE_Y_IX |     1 |       |     1   (0)| 00:00:01 |
    ------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       2 - access("COL_A"='STACKOVERFLOW')
    

    ID 2 告诉您,索引 TABLE_Y_IX 确实用于 index range scan

    如果在另一个安装上,Oracle 选择使用索引取决于很多事情。做出此决定的是 Oracle 的查询优化器

    更新如果您觉得如果 Oracle 使用索引会更好(即性能方面),您可能想尝试+ index_asc(...)(请参阅index hint

    所以你的情况是这样的

    SELECT /*+ index_asc(TABLE_Y TABLE_Y_IX) */ * 
      FROM Table_Y 
     WHERE Col_A = 'STACKOVERFLOW';
    

    此外,我会确保您已收集有关表及其列的统计信息。您可以使用

    检查上次收集统计数据的日期
    select last_analyzed from dba_tables where table_name = 'TABLE_Y';
    

    select column_name, last_analyzed from dba_tab_columns where table_name = 'TABLE_Y';
    

    如果没有统计信息或者它们已经过时,请熟悉 dbms_stats 包以收集此类统计信息。

    这些统计数据是查询优化器在做出决策时非常依赖的数据。

    【讨论】:

    • 完美,帮助很大。顺便说一句,我的安装报告了表扫描,但至少我现在有能力检查。
    • 只是想知道。执行计划的选择不取决于您是选择索引中的第一列还是第二列。也就是说,如果您选择第一列,您将获得索引范围扫描,但如果您选择第二列,您将获得全表扫描?
    • @Gisli:Oracle 可能会选择在您的场景中使用index skip scan 的索引。
    • @RenéNyffenegger,大溪地和索引提示的链接已损坏。你能更新一下吗?
    • @ajmalmhd04 我已经更新了第二个断开的链接。我无法找到旧链接的新目的地,所以我删除了它。具有讽刺意味的是,销售主键概念的供应商无法保持其网址不变。
    猜你喜欢
    • 2020-05-06
    • 1970-01-01
    • 2013-11-05
    • 1970-01-01
    • 2019-09-17
    • 1970-01-01
    • 1970-01-01
    • 2017-02-06
    • 2010-12-24
    相关资源
    最近更新 更多