这里给出通过使用Hint的方法实现强制SQL不走特定索引的方法。
在众多Oracle Hint中我们选中了“NO_INDEX”。
1.环境准备
1)创建表T
sec@ora10g> create table t as select * from all_objects;
Table created.
sec@ora10g> select count(*) from t;
COUNT(*)
----------
11139
2)在object_name列上创建索引t_idx1
sec@ora10g> create index t_idx1 on t(object_name);
Index created.
3)在object_id列上创建索引t_idx2
sec@ora10g> create index t_idx2 on t(object_id);
Index created.
2.未使用“NO_INDEX”提示时索引使用情况
sec@ora10g> set autotrace on
sec@ora10g> select object_name from t where object_name = 'T';
OBJECT_NAME
------------------------------
T
Execution Plan
----------------------------------------------------------
Plan hash value: 3419373504
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 17 | 1 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| T_IDX1 | 1 | 17 | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------
……省略其他信息输出……
sec@ora10g> select object_name from t where object_id = 11915;
OBJECT_NAME
------------------------------
T
Execution Plan
----------------------------------------------------------
Plan hash value: 3371054274
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 30 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 30 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | T_IDX2 | 1 | | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
……省略其他信息输出……
可见以上两条SQL语句均能正常使用到索引。
3.使用“NO_INDEX”提示时索引使用情况
sec@ora10g> select /*+ NO_INDEX(t t_idx1) */ object_name from t where object_name = 'T';
OBJECT_NAME
------------------------------
T
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 34 | 35 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T | 2 | 34 | 35 (0)| 00:00:01 |
--------------------------------------------------------------------------
……省略其他信息输出……
sec@ora10g> select /*+ NO_INDEX(t t_idx2) */ object_name from t where object_id = 11915;
OBJECT_NAME
------------------------------
T
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 60 | 35 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T | 2 | 60 | 35 (0)| 00:00:01 |
--------------------------------------------------------------------------
……省略其他信息输出……
此处均显示为使用到对应的索引进行检索数据。我们的实验目标已经实现。
4.“NO_INDEX”提示的用法补充说明
1)Oracle 10g官方文档中关于no_index这个HINT的描述信息参见如下链接
http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/sql_elements006.htm#SQLRF50411
NO_INDEX Hint
Description of the illustration no_index_hint.gif
(See "Specifying a Query Block in a Hint", tablespec::=, indexspec::=)
The NO_INDEX hint instructs the optimizer not to use one or more indexes for the specified table. For example:
SELECT /*+ NO_INDEX(employees emp_empid) */ employee_id
FROM employees
WHERE employee_id > 200;
Each parameter serves the same purpose as in "INDEX Hint" with the following modifications:
-
If this hint specifies a single available index, then the optimizer does not consider a scan on this index. Other indexes not specified are still considered.
-
If this hint specifies a list of available indexes, then the optimizer does not consider a scan on any of the specified indexes. Other indexes not specified in the list are still considered.
-
If this hint specifies no indexes, then the optimizer does not consider a scan on any index on the table. This behavior. is the same as a NO_INDEX hint that specifies a list of all available indexes for the table.
The NO_INDEX hint applies to function-based, B-tree, bitmap, cluster, or domain indexes. If a NO_INDEX hint and an index hint (INDEX, INDEX_ASC, INDEX_DESC, INDEX_COMBINE, or INDEX_FFS) both specify the same indexes, then the database ignores both the NO_INDEX hint and the index hint for the specified indexes and considers those indexes for use during execution of the statement.
2)在一条SQL中可以给出多个索引名称,以便在执行SQL时避免使用这些索引。
sec@ora10g> select /*+ NO_INDEX(t t_idx2 t_idx1) */ object_name from t where object_id = 11915;
OBJECT_NAME
------------------------------
T
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 60 | 35 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T | 2 | 60 | 35 (0)| 00:00:01 |
--------------------------------------------------------------------------
……省略其他信息输出……
3)当任何索引都不列出的情况下表示T表上的所有索引都不被使用!
sec@ora10g> select /*+ NO_INDEX (t) */ object_name from t where object_id = 11915;
OBJECT_NAME
------------------------------
T
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 60 | 35 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T | 2 | 60 | 35 (0)| 00:00:01 |
--------------------------------------------------------------------------
……省略其他信息输出……
5.小结
在SQL优化中使用Hint提示的方法往往是万不得已而为止的行为。不过本文中提到的方法也可以用于SQL语句的调试和故障排除。灵活使用之。
Good luck.
secooler
11.05.04
-- The End --
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/519536/viewspace-694457/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/519536/viewspace-694457/