我在一次采访中遇到了这个问题,并且不知道如何回答:
有一个表在列上有索引,您查询:
select * from table_name where column_having_index="some value";
查询过长,您发现索引未被使用。如果您认为使用索引查询的性能会更好,您如何强制查询使用索引?
答案 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)