SQL/Oracle:当可以使用多列上的索引时

SQL/Oracle:当可以使用多列上的索引时,oracle,indexing,Oracle,Indexing,如果我按顺序在A、B、C列上创建索引,我的理解是,即使我只在A、A和B、A和B和C上搜索,数据库也可以使用它,但如果我只在B、C、B和C上搜索,则不能使用它。这是否正确?这是不正确的。总是最好拿出一个代表您的数据并亲自查看的测试用例。如果你想真正了解oraclesql优化器googlejonathanlewis,阅读他的书籍,阅读他的博客,查看他的网站,这个家伙很了不起,他总是生成测试用例 create table mytab nologging as ( select mod(rownum,

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

这是不正确的。总是最好拿出一个代表您的数据并亲自查看的测试用例。如果你想真正了解oraclesql优化器googlejonathanlewis,阅读他的书籍,阅读他的博客,查看他的网站,这个家伙很了不起,他总是生成测试用例

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)
在Oracle 8版本之前,除非SQL中包含第一列,否则永远不会使用索引

在Oracle 9i中引入了跳过扫描索引访问功能,该功能允许Oracle CBO在前缀列不可用时尝试使用索引


这里很好地概述了跳过扫描的工作原理:

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

i索引跳过扫描:

ii快速全索引扫描:

iii索引完整扫描:


我经常在野外看到快速完整索引扫描,但所有这些都是可能的。

+1提及乔纳森·刘易斯和这个例子。甲骨文是否针对A,C案例进行了优化?@kd304我不确定除了快速完整索引扫描之外,是否还有其他优化方法可用,尽管A上的范围扫描可能可用。它肯定会依赖于版本。当然,问题在于是否可以使用Optimizer提示有效地推送某些扫描类型,而不是让Optimizer自己做事情。