一、如何使用 /*+ index()*/
The format for an index hint is:
select /*+ index(TABLE_NAME INDEX_NAME) */ col1...
There are a number of rules that need to be applied to this hint:
1 The TABLE_NAME is mandatory in the hint
2 The table alias MUST be used if the table is aliased in the query
3 If TABLE_NAME or alias is spelled incorrectly then the hint will not be used.
4 The INDEX_NAME is optional.
5 If an INDEX_NAME is entered without a TABLE_NAME then the hint will not be
applied.
6 If a TABLE_NAME is supplied on its own then the optimizer will decide
which index to use based on statistics.
7 If the INDEX_NAME is spelt incorrectly but the TABLE_NAME is spelled correctly
then the hint will not be applied even though the TABLE_NAME is correct.
8 If there are multiple index hints to be applied, then the simplest way of
addressing this is to repeat the index hint syntax for each index e.g.:
select /*+ index(TABLE_NAME1 INDEX_NAME1) index(TABLE_NAME2 INDEX_NAME2) */ col1...
9 Remember that the parser/optimizer may have transformed/rewritten the query
or may have chosen an access path which make the use of the index invalid and
this may result in the index not being used.
NB Please note that as long as the index() hint structure is correct
it will force the use of the Cost Based Optimizer (CBO). This will happen
even if the alias or table name is incorrect.
二、测试
SQL> select /*+index(t1) */empno from t1;
已选择12行。
执行计划
----------------------------------------------------------
Plan hash value: 3617692013
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 12 | 48 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| T1 | 12 | 48 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
通过测试发现,此hints 没有起作用,但是也没有什么地方写错,最后加了一个主键后,走hints
SQL> select /*+ index(t1)*/t1.ename from T1;
已选择12行。
执行计划
----------------------------------------------------------
Plan hash value: 1552010074
------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 12 | 72 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T1 | 12 | 72 | 2 (0)| 00:00:01 |
| 2 | INDEX FULL SCAN | II | 12 | | 1 (0)| 00:00:01 |
------------------------------------------------------------------------------------
下面我们逐一测试:
1、 index() 里的table_name 是强制性的提示,index_name是可选性的,如果 table_name 有别名,那么hints 中的表名也必须用别名 SQL> select /*+ index(t1)*/ ename from T1 a; 已选择12行。 执行计划 ---------------------------------------------------------- Plan hash value: 3617692013 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 12 | 72 | 3 (0)| 00:00:01 | | 1 | TABLE ACCESS FULL| T1 | 12 | 72 | 3 (0)| 00:00:01 | -------------------------------------------------------------------------- 2、hints中 index()里的table_name 是必须的,但是index_name不是必须的,也就是说hints中只写index_name不写table_name,那么hints不会被使用 SQL> select /*+ index(ind_t1)*/ ename from T1 a; 已选择12行。 执行计划 ---------------------------------------------------------- Plan hash value: 3617692013 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 12 | 72 | 3 (0)| 00:00:01 | | 1 | TABLE ACCESS FULL| T1 | 12 | 72 | 3 (0)| 00:00:01 | -------------------------------------------------------------------------- 3、如果hints中的table_name或者别名写的不正确,那么hints就不会被使用 SQL> select /*+ index(aa)*/ ename from T1 a; 已选择12行。 执行计划 ---------------------------------------------------------- Plan hash value: 3617692013 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 12 | 72 | 3 (0)| 00:00:01 | | 1 | TABLE ACCESS FULL| T1 | 12 | 72 | 3 (0)| 00:00:01 | -------------------------------------------------------------------------- SQL> select /*+ index(a ii_t1)*/ ename from T1 a; 已选择12行。 执行计划 ---------------------------------------------------------- Plan hash value: 3617692013 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 12 | 72 | 3 (0)| 00:00:01 | | 1 | TABLE ACCESS FULL| T1 | 12 | 72 | 3 (0)| 00:00:01 | -------------------------------------------------------------------------- 4、如果hints中写了table_name不写索引名,那么优化器会根据统计信息选择索引 QL> select /*+ index(a)*/ ename from T1 a; 已选择12行。 执行计划 --------------------------------------------------------- lan hash value: 1552010074 ----------------------------------------------------------------------------------- Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ----------------------------------------------------------------------------------- 0 | SELECT STATEMENT | | 12 | 72 | 2 (0)| 00:00:01 | 1 | TABLE ACCESS BY INDEX ROWID| T1 | 12 | 72 | 2 (0)| 00:00:01 | 2 | INDEX FULL SCAN | II | 12 | | 1 (0)| 00:00:01 | ----------------------------------------------------------------------------------- 5、如果hints中的table_name 写错,而索引写正确 ,那么hints就不会被使用 SQL> select /*+ index(aa ii )*/ ename from T1 a; 已选择12行。 执行计划 ---------------------------------------------------------- Plan hash value: 3617692013 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 12 | 72 | 3 (0)| 00:00:01 | | 1 | TABLE ACCESS FULL| T1 | 12 | 72 | 3 (0)| 00:00:01 | -------------------------------------------------------------------------- 7、如果有多个索引要使用那么可以使用 /*+ index(TABLE_NAME1 INDEX_NAME1) index(TABLE_NAME2 INDEX_NAME2) */