在Oracle中强制使用索引

时间:2009-12-03 06:37:37

标签: sql oracle indexing sqlplus

我在一次采访中遇到了这个问题,并且不知道如何回答:

有一个表在列上有索引,您查询:

select * from table_name where column_having_index="some value";

查询过长,您发现索引未被使用。如果您认为使用索引查询的性能会更好,您如何强制查询使用索引?

6 个答案:

答案 0 :(得分:43)

您可以使用优化程序提示

select /*+ INDEX(table_name index_name) */ from table等......

有关使用优化程序提示的更多信息: http://download.oracle.com/docs/cd/B19306_01/server.102/b14211/hintsref.htm

答案 1 :(得分:13)

可能有很多原因没有使用Index。即使在您 specify hints 之后,Oracle优化工具也有可能认为不是这样,决定不使用Index 。您需要浏览EXPLAIN PLAN部分,看看使用INDEX和没有INDEX的语句的成本是多少。

假设Oracle uses CBO。大多数情况下,如果优化器认为INDEX的成本很高,即使您在提示中指定它,优化器也会忽略并继续进行全表扫描。您的第一个操作应该是检查DBA_INDEXES以了解统计信息何时为LAST_ANALYZED。如果未分析,您可以set table, index for analyze

begin 
   DBMS_STATS.GATHER_INDEX_STATS ( OWNNAME=>user
                                 , INDNAME=>IndexName);
end;

表格。

begin 
   DBMS_STATS.GATHER_TABLE_STATS ( OWNNAME=>user
                                 , TABNAME=>TableName);
end;

在极端情况下,您可以自行尝试setting up the statistics

答案 2 :(得分:12)

  

如果您认为使用索引查询的性能会更好,您如何强制查询使用索引?

首先,您当然要验证索引是否为返回完整数据集提供了更好的结果,对吗?

索引提示是这里的关键,但是更新的指定方法是使用列命名方法而不是索引命名方法。在您的情况下,您将使用:

select /*+ index(table_name (column_having_index)) */ *
from   table_name
where  column_having_index="some value"; 

在更复杂的情况下,你可能......

select /*+ index(t (t.column_having_index)) */ *
from   my_owner.table_name t,
       ...
where  t.column_having_index="some value"; 

关于复合索引,我不确定你需要来指定所有列,但这似乎是一个好主意。请参阅此处的文档http://docs.oracle.com/cd/E11882_01/server.112/e26088/sql_elements006.htm#autoId18以及多个index_specs和index_combine用于多个索引,此处http://docs.oracle.com/cd/E11882_01/server.112/e26088/sql_elements006.htm#BABGFHCH用于index_spec中多列的规范。

答案 3 :(得分:2)

column_having_index上有一个合适的索引,它的使用实际上提高了性能,但Oracle没有使用它...
您应该在表上收集统计信息,让优化程序看到索引访问权限可以提供帮助。使用直接提示不是一个好习惯。

答案 4 :(得分:1)

我尝试了很多格式,但只有一种有效:

select /*+INDEX(e,dept_idx)*/ * from emp e;

答案 5 :(得分:-4)

您可以使用:

WITH index = ...

more info