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
我最经常看到的是在野外快速进行全索引扫描的方法,但是一切皆有可能。