【问题标题】:SQL/Oracle: when indexes on multiple columns can be usedSQL/Oracle:当可以使用多列索引时
【发布时间】:2010-09-08 15:26:26
【问题描述】:

如果我按顺序在列(A、B、C)上创建索引,我的理解是即使我只在(A)或(A 和 B)上搜索,数据库也能使用它, 或 (A and B and C), 但如果我只搜索 (B), or (C), or (B and C), 则不是。这是正确的吗?

【问题讨论】:

    标签: oracle indexing


    【解决方案1】:

    当谓词放在索引的非前导列上时,Oracle 可以使用三种基于索引的访问方法。

    i) 索引跳过扫描:http://download.oracle.com/docs/cd/B19306_01/server.102/b14211/optimops.htm#PFGRF10105

    ii) 快速全索引扫描:http://download.oracle.com/docs/cd/B19306_01/server.102/b14211/optimops.htm#i52044

    iii) 索引全扫描:http://download.oracle.com/docs/cd/B19306_01/server.102/b14211/optimops.htm#i82107

    我经常“在野外”看到快速全索引扫描,但一切皆有可能。

    【讨论】:

    • Oracle 是否针对 (A, C) 情况进行了优化?
    • @kd304 我不确定除了快速全索引扫描之外是否还有其他优化方法可用,尽管 A 上的范围扫描可能可用。它肯定取决于版本。当然,是否可以使用优化器提示有效地“推动”某些扫描类型,而不是让优化器自己做事。
    【解决方案2】:

    这是不正确的。总是最好拿出一个代表您的数据的测试用例并亲自查看。如果你想真正了解 Oracle SQL Optimizer google Jonathan Lewis,阅读他的书籍、阅读他的博客、查看他的网站,这个人很棒,而且他总是会生成测试用例。

    create table mytab nologging as (
    select mod(rownum, 3) x, rownum  y, mod(rownum, 3) z from all_objects, (select 'x' from user_tables where rownum < 4)
    );
    
    create index i on mytab (x, y, z);
    
    exec dbms_stats.gather_table_stats(ownname=>'DBADMIN',tabname=>'MYTAB', cascade=>true);
    
    set autot trace exp
    
    select * from mytab where y=5000;
    
    Execution Plan
    ----------------------------------------------------------
       0      SELECT STATEMENT Optimizer=CHOOSE (Cost=1 Card=1 Bytes=10)
       1    0   INDEX (SKIP SCAN) OF 'I' (INDEX) (Cost=1 Card=1 Bytes=10)
    

    【讨论】:

    • +1 用于提及乔纳森·刘易斯和示例。
    【解决方案3】:

    直到版本 Oracle 8,除非第一列包含在 SQL 中,否则永远不会使用索引。

    在 Oracle 9i 中,引入了跳过扫描索引访问 特性,即使前缀列不可用,Oracle CBO 也可以尝试使用索引。

    这里很好地概述了跳过扫描的工作原理:http://www.quest-pipelines.com/newsletter-v5/1004_C.htm

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-06
      • 1970-01-01
      • 2021-03-09
      • 2019-01-08
      • 2021-05-11
      • 2012-06-28
      相关资源
      最近更新 更多