Oracle 中强制使用索引

发布于 2024-08-13 10:35:40 字数 203 浏览 9 评论 0原文

我在面试中遇到这个问题,不知道如何回答:

有一张表,其中某列有索引,你查询:

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

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

I encountered this question in an interview and had no clue how to answer:

There is a table which has a index on a column, and you query:

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

The query takes too long, and you find out that the index is not being used. If you think the performance of the query will be better using the index, how could you force the query to use the index?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

泡沫很甜 2024-08-20 10:35:40

您可以使用优化器提示

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

有关使用优化器提示的更多信息

You can use optimizer hints

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

More on using optimizer hints

蛮可爱 2024-08-20 10:35:40

未使用索引可能有多种原因。即使您指定提示< /strong>,Oracle 优化器有可能不这么想并决定不使用索引。您需要仔细检查 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;

在极端情况下,您可以尝试设置统计信息 靠你自己。

There could be many reasons for Index not being used. Even after you specify hints, there are chances Oracle optimizer thinks otherwise and decide not to use Index. You need to go through the EXPLAIN PLAN part and see what is the cost of the statement with INDEX and without INDEX.

Assuming the Oracle uses CBO. Most often, if the optimizer thinks the cost is high with INDEX, even though you specify it in hints, the optimizer will ignore and continue for full table scan. Your first action should be checking DBA_INDEXES to know when the statistics are LAST_ANALYZED. If not analyzed, you can set table, index for analyze.

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

For table.

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

In extreme cases, you can try setting up the statistics on your own.

随梦而飞# 2024-08-20 10:35:40

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

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

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

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

If you think the performance of the query will be better using the index, how could you force the query to use the index?

First you would of course verify that the index gave a better result for returning the complete data set, right?

The index hint is the key here, but the more up to date way of specifying it is with the column naming method rather than the index naming method. In your case you would use:

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

In more complex cases you might ...

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

With regard to composite indexes, I'm not sure that you need to specify all columns, but it seems like a good idea. See the docs here http://docs.oracle.com/cd/E11882_01/server.112/e26088/sql_elements006.htm#autoId18 on multiple index_specs and use of index_combine for multiple indexes, and here http://docs.oracle.com/cd/E11882_01/server.112/e26088/sql_elements006.htm#BABGFHCH for the specification of multiple columns in the index_spec.

场罚期间 2024-08-20 10:35:40

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

There is an appropriate index on column_having_index, and its use actually increase performance, but Oracle didn't use it...
You should gather statistics on your table to let optimizer see that index access can help. Using direct hint is not a good practice.

策马西风 2024-08-20 10:35:40

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

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

I tried many formats, but only that worked:

select /*+INDEX(e,dept_idx)*/ * from emp e;
很糊涂小朋友 2024-08-20 10:35:40

您可以使用:

WITH index = ...

更多信息

You can use:

WITH index = ...

more info

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文