ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 【HINT】使用“NO_INDEX ”Hint提示避免SQL使用特定索引

【HINT】使用“NO_INDEX ”Hint提示避免SQL使用特定索引

原创 Linux操作系统 作者:secooler 时间:2011-05-04 23:20:07 0 删除 编辑
  在生产环境的SQL调优测试过程中经常遇到如下场景:一张表上创建了非常多的索引(不推荐),每一个索引都是针对特定业务查询而增加的。这极易导致SQL由于个别索引的引入出现性能问题,在这种情况下不能简简单单的将索引删除在解决问题。如何避免SQL不使用特定索引这个问题便摆在了我们面前。

  这里给出通过使用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

De.ion of no_index_hint.gif follows
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/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
Oracle ACE 总监,阿里云MVP,北京大学理学硕士,恩墨学院创始人,教育专家,中国区 Cloudera 首位官方授权大数据讲师,金牌培训专家,BDA大数据联盟创始人,OCM联盟创始人,ACCUG创始人、ACOUG核心专家,Blogger。

注册时间:2008-03-16

  • 博文量
    797
  • 访问量
    8092054