【问题标题】:How to Force Oracle to use indexes in inline view of a query with "order by" clause如何强制 Oracle 在带有“order by”子句的查询的内联视图中使用索引
【发布时间】:2021-06-18 15:17:48
【问题描述】:

甲骨文 11g

我有一个查询,其示意图如下所示:

select *
from
(
  --My inline view
  select ...
)
order by
  field1, field2;

我的内联视图是来自多个带有索引的表的复杂查询。

如果我只执行内联视图,使用索引和查询的 Oracle 会执行得很快。 但是如果执行整个查询,Oracle 不使用索引并且查询执行速度很慢。

我找到了一种解决方案(使用两个步骤):

-- 1. I just creating temp table from my inline view (no sorting)
create global temporary table tmp
on commit preserve rows
as
--My inline view (Here Oracle using indexes and query runs fast)
select ...

-- 2. Now I sort it (result set is not very large and this runs also fast)
select * 
from tmp
order by
  field1, field2;

但如果可能的话,我想使用更简单的方法而不使用临时表。

我尝试使用“with” - 不走运,同样的问题。

很抱歉没有发布实际查询。它只是太复杂了,很难编写说明问题的示例脚本。

更新

子查询是来自表SLOT, SLOT_O 的多个UNION ALL 与表TLG_INFORM 左连接。 TLG_INFORM 有一个索引IDX_TLG_INFORM_PAIR,不带ORDER BY 使用,不带ORDER BY

执行计划:

没有ORDER BY

ORDER BY

我尝试使用WITH 和提示/*+MATERIALIZE*/。没有运气。此外,如果没有ORDER BY,也不会使用带有提示/*+MATERIALIZE*/ 的索引。

在没有ORDER BY 的情况下实现。

ORDER BY 实现。

【问题讨论】:

  • 尝试消除外部查询并将ORDER BY 添加到内联视图中,例如SELECT ... (inline view code)... ORDER BY FIELD1, FIELD2。其他选项:将内联视图转换为 CTE:WITH cteIV AS (<inline view code here>) SELECT * FROM cteIV ORDER BY FIELD1, FIELD2。如果没有表格、索引和示例数据等说明问题的细节,我看不到具体的方法。祝你好运。
  • 我都试过了:对内联视图代码本身和“with”进行排序。都一样。
  • 你在用什么optimizer_mode?这听起来像是一个 first_rows% 风格的计划,它现在在一个涵盖您的 order by 子句的索引上领先。
  • optimizer_modeALL_ROWS
  • 收集所有涉及的表的统计信息并尝试再次运行它。然后 - (FIELD1, FIELD2) 上是否有索引?如果没有,请添加一个,收集统计信息,然后重试。此外,检查计划以了解发生了什么 - 但没有具体细节,我们只能猜测。所以我想就是这样。

标签: oracle indexing oracle11g sql-order-by inline-view


【解决方案1】:

该问题可能表明 DBMS 对您的数据不够了解。更新表统计信息可能会有所帮助。

但也许这确实是优化器的一个缺陷。您应该能够通过具体化的 CTE 规避此问题:

with my_inline_view as (select /*+materialize*/ ...)
select *
from my_inline_view
order by field1, field2;

【讨论】:

  • 我试过了。我得到了奇怪的结果。在子查询中使用/*MATERIALIZE*/ 提示时,它在两种情况下都不使用索引:使用order by 和没有order by 并且执行速度很慢。看来,/*MATERIALIZE*/ 暗示“压制”使用索引。没有/*MATERIALIZE*/ 提示,也没有order by,它使用索引并且运行速度很快。
【解决方案2】:

好的,如果没有具体细节,很难找到。由于查询的复杂性,发布示例脚本也非常困难,所以我之前发布的解决方案是临时表。

对临时表进行复杂查询的结果。 并从需要排序的表中选择。 可能,这是唯一的方法。

【讨论】:

    猜你喜欢
    • 2018-01-17
    • 2012-04-02
    • 2011-10-03
    • 1970-01-01
    • 2021-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-29
    相关资源
    最近更新 更多