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

时间:2020-03-05 18:51:55  来源:igfitidea点击:

如果按此顺序在列(A,B,C)上创建索引,则我的理解是,即使仅在(A)或者(A和B)或者( A和B和C),但如果我仅在(B)或者(C)或者(B和C)上搜索,则不会。这样对吗?

解决方案

回答

那是不对的。始终最好拿出一个代表数据的测试用例,然后亲自看看。如果我们想真正了解Oracle SQL Optimizer谷歌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)

回答

在Oracle 8之前的版本中,除非SQL中包括第一列,否则将永远不会使用索引。

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

有关跳过扫描工作原理的完整概述,请访问:http://www.quest-pipelines.com/newsletter-v5/1004_C.htm

回答

当将谓词放在索引的非前导列上时,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

我最经常看到的是在野外快速进行全索引扫描的方法,但是一切皆有可能。