42

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

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

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

查询时间过长,您发现索引没有被使用。如果你认为使用索引查询的性能会更好,你怎么能强制查询使用索引呢?

4

6 回答 6

57

您可以使用优化器提示

select /*+ INDEX(table_name index_name) */ from tableETC...

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

于 2009-12-03T06:40:30.783 回答
17

没有使用索引可能有很多原因。即使在您指定了提示之后,Oracle 优化器也有可能不这样认为并决定不使用 Index。您需要通过 EXPLAIN PLAN 部分,看看有 INDEX 和没有 INDEX 的语句的成本是多少。

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

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

为表。

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

在极端情况下,您可以尝试自行设置统计信息

于 2009-12-03T07:13:06.470 回答
15

如果你认为使用索引查询的性能会更好,你怎么能强制查询使用索引呢?

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

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

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 中多列的规范。

于 2009-12-03T07:53:33.957 回答
3

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

于 2009-12-03T07:09:54.290 回答
1

我尝试了许多格式,但只有这样有效:

select /*+INDEX(e,dept_idx)*/ * from emp e;
于 2021-02-19T13:29:21.180 回答
-5

您可以使用:

WITH index = ...

更多信息

于 2009-12-03T06:42:50.963 回答