SQL > create index test.ind_fun on test.testindex( upper (a)); 索引已创建。 SQL > insert into testindex values ( ' a ' , 2 ); 已创建 1 行。 SQL > commit ; 提交完成。 SQL > select /**/ /*+ RULE*/ * FROM test.testindex where upper (a) = ' A ' ; A B -- ---------- a 2 Execution Plan -- -------------------------------------------------------- 0 SELECT STATEMENT Optimizer = HINT: RULE 1 0 TABLE ACCESS ( FULL ) OF ' TESTINDEX ' (优化器选择了全表扫描) -- ------------------------------------------------------------------ SQL > select * FROM test.testindex where upper (a) = ' A ' ; A B -- ---------- a 2 Execution Plan -- -------------------------------------------------------- 0 SELECT STATEMENT Optimizer = CHOOSE (Cost = 2 Card = 1 Bytes = 5 ) 1 0 TABLE ACCESS ( BY INDEX ROWID) OF ' TESTINDEX ' (Cost = 2 Card = 1 Bytes = 5 ) 2 1 INDEX (RANGE SCAN) OF ' IND_FUN ' (NON - UNIQUE ) (Cost = 1 Car d = 1 )(使用了ind_fun索引)
SQL > set autotrace on SQL > select * from test; A -- -------- 1 Execution Plan -- -------------------------------------------------------- 0 SELECT STATEMENT Optimizer = CHOOSE 1 0 TABLE ACCESS ( FULL ) OF ' TEST ' Statistics -- -------------------------------------------------------- 0 recursive calls 0 db block gets 0 consistent gets 0 physical reads 0 redo size 0 bytes sent via SQL * Net to client 0 bytes received via SQL * Net from client 0 SQL * Net roundtrips to / from client 0 sorts (memory) 0 sorts ( disk ) rows processed SQL > set autotrace traceonly SQL > select * from test.test; Execution Plan -- -------------------------------------------------------- 0 SELECT STATEMENT Optimizer = CHOOSE 1 0 TABLE ACCESS ( FULL ) OF ' TEST ' Statistics -- -------------------------------------------------------- 0 recursive calls 0 db block gets 0 consistent gets 0 physical reads 0 redo size 0 bytes sent via SQL * Net to client 0 bytes received via SQL * Net from client 0 SQL * Net roundtrips to / from client 0 sorts (memory) 0 sorts ( disk ) rows processed
SQL > create table test.testindex (a varchar ( 2 ),b number ); 表已创建。 SQL > create index ind_cola on test.testindex(a); 索引已创建。 SQL > insert into test.testindex values ( ' 1 ' , 1 ); 已创建 1 行。 SQL > commit ; 提交完成。 SQL > analyze table test.testindex compute statistics for all indexes; 表已分析。 SQL > set autotrace on ; SQL > select /**/ /*+RULE */ * FROM test.testindex where a = ' 1 ' ;(使用基于rule的优化器,数据类型匹配的情况下) A B -- ---------- 1 1 Execution Plan -- -------------------------------------------------------- 0 SELECT STATEMENT Optimizer = HINT: RULE 1 0 TABLE ACCESS ( BY INDEX ROWID) OF ' TESTINDEX ' 2 1 INDEX (RANGE SCAN) OF ' IND_COLA ' (NON - UNIQUE )(使用了索引ind_cola) �D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D SQL > select /**/ /*+RULE */ * FROM test.testindex where a = 1 ;(数据类型不匹配的情况) A B -- ---------- 1 1 Execution Plan -- -------------------------------------------------------- 0 SELECT STATEMENT Optimizer = HINT: RULE 1 0 TABLE ACCESS ( FULL ) OF ' TESTINDEX ' (优化器选择了全表扫描)
SQL > select /**/ /*+ RULE */ * FROM test.testindex where upper (a) = ' A ' ;(使用了函数upper()在列a上); A B -- ---------- a 2 Execution Plan -- -------------------------------------------------------- 0 SELECT STATEMENT Optimizer = HINT: RULE 1 0 TABLE ACCESS ( FULL ) OF ' TESTINDEX ' (优化器选择全表扫描) -- -------------------------------------------------------- 创建基于函数的索引 SQL > create index test.ind_fun on test.testindex( upper (a)); 索引已创建。 SQL > insert into testindex values ( ' a ' , 2 ); 已创建1行。 SQL > commit ; 提交完成。 SQL > select /**/ /*+ RULE*/ * FROM test.testindex where upper (a) = ' A ' ; A B -- ---------- a 2 Execution Plan -- -------------------------------------------------------- 0 SELECT STATEMENT Optimizer = HINT: RULE 1 0 TABLE ACCESS ( FULL ) OF ' TESTINDEX ' (在RULE优化器下忽略了函数索引选择了全表扫描) -- --------------------------------------------------------- SQL > select * FROM test.testindex where upper (a) = ' A ' ; A B -- ---------- a 2 Execution Plan -- -------------------------------------------------------- 0 SELECT STATEMENT Optimizer = CHOOSE (Cost = 2 Card = 1 Bytes = 5 ) 1 0 TABLE ACCESS ( BY INDEX ROWID) OF ' TESTINDEX ' (Cost = 2 Card = 1 Bytes = 5 ) 2 1 INDEX (RANGE SCAN) OF ' IND_FUN ' (NON - UNIQUE ) (Cost = 1 Car d = 1 )(CBO优化器使用了ind_fun索引)
创建一个复合索引 SQL > create index ind_com on test.testindex(a,b); 索引已创建。 SQL > select /**/ /*+ RULE*/ * from test.testindex where a = ' 1 ' ; A B -- ---------- 1 2 Execution Plan -- -------------------------------------------------------- 0 SELECT STATEMENT Optimizer = HINT: RULE 1 0 INDEX (RANGE SCAN) OF ' IND_COM ' (NON - UNIQUE )(条件列表包含前导列时使用索引ind_com) SQL > select /**/ /*+ RULE*/ * from test.testindex where b = 1 ; 未选定行 Execution Plan -- -------------------------------------------------------- 0 SELECT STATEMENT Optimizer = HINT: RULE 1 0 TABLE ACCESS ( FULL ) OF ' TESTINDEX ' (条件列表不包括前导列是选择全表扫描) -- ---------------------------------------------------------
SQL > select * from test.testindex where a = ' 1 ' ; A B -- ---------- 1 2 Execution Plan -- -------------------------------------------------------- 0 SELECT STATEMENT Optimizer = CHOOSE (Cost = 1 Card = 1 Bytes = 5 ) 1 0 TABLE ACCESS ( FULL ) OF ' TESTINDEX ' (Cost = 1 Card = 1 Bytes = 5 ) (表一共2行,选择比例为50 % ,所以优化器选择了全表扫描) �D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D 下面增加表行数 SQL > declare i number ; 2 begin 3 for i in 1 .. 100 loop 4 insert into test.testindex values (to_char(i),i); 5 end loop; 6 end ; 7 / PL / SQL 过程已成功完成。 SQL > commit ; 提交完成。 SQL > select count ( * ) from test.testindex; COUNT ( * ) -- -------- 102 SQL > select * from test.testindex where a = ' 1 ' ; A B -- -- ---------- 1 1 1 2 Execution Plan SELECT STATEMENT Optimizer = CHOOSE (Cost = 1 Card = 1 Bytes = 5 ) 1 0 INDEX (RANGE SCAN) OF ' IND_COM ' (NON - UNIQUE ) (Cost = 1 Card = 1 Bytes = 5 ) (表一共102行,选择比例为2 / 102 = 2 % ,所以优化器选择了索引扫描)
SQL > select * from test.testindex where a like ' 1% ' ; A B -- -- ---------- 1 2 1 1 10 10 11 11 12 12 13 13 14 14 15 15 16 16 17 17 18 18 19 19 100 100 已选择13行。 Execution Plan -- -------------------------------------------------------- 0 SELECT STATEMENT Optimizer = CHOOSE (Cost = 1 Card = 13 Bytes = 52 ) 1 0 TABLE ACCESS ( FULL ) OF ' TESTINDEX ' (Cost = 1 Card = 13 Bytes = 52 ) (表一共102行,选择比例为13 / 102 > 10 % ,优化器选择了全表扫描) �D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D 增加表行数 SQL > declare i number ; 2 begin 3 for i in 200 .. 1000 loop 4 insert into test.testindex values (to_char(i),i); 5 end loop; 6 end ; 7 / PL / SQL 过程已成功完成。 SQL > commit ; 提交完成。 SQL > select count ( * ) from test.testindex; COUNT ( * ) -- -------- 903 SQL > select * from test.testindex where a like ' 1% ' ; A B -- -- ---------- 1 2 1 1 10 10 11 11 12 12 13 13 14 14 15 15 16 16 17 17 18 18 19 19 100 100 1000 1000 已选择14行。 Execution Plan -- -------------------------------------------------------- 0 SELECT STATEMENT Optimizer = CHOOSE (Cost = 1 Card = 13 Bytes = 52 ) 1 0 TABLE ACCESS ( FULL ) OF ' TESTINDEX ' (Cost = 1 Card = 13 Bytes = 52 ) (表一共903行,选择比例为14 / 903 < 5 % ,优化器选择了全表扫描,选择路径是错误的) �D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D 给表做分析 SQL > analyze table test.testindex compute statistics for table for all indexed c olumns for all indexes; 表已分析。 SQL > select * from test.testindex where a like ' 1% ' ; A B -- -- ---------- 1 2 1 1 10 10 100 100 1000 1000 11 11 12 12 13 13 14 14 15 15 16 16 17 17 18 18 19 19 已选择14行。 Execution Plan -- -------------------------------------------------------- 0 SELECT STATEMENT Optimizer = CHOOSE (Cost = 4 Card = 24 Bytes = 120 ) 1 0 TABLE ACCESS ( BY INDEX ROWID) OF ' TESTINDEX ' (Cost = 4 Card = 24 Bytes = 120 ) 2 1 INDEX (RANGE SCAN) OF ' IND_COLA ' (NON - UNIQUE ) (Cost = 2 Ca rd = 24 ) (经过分析后优化器选择了正确的路径,使用了ind_cola索引) �D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D