【问题标题】:Forcing Oracle to do distinct last迫使 Oracle 最后做不同的事情
【发布时间】:2013-09-03 05:16:30
【问题描述】:

我有一个相当复杂的视图(在多个数据库链接中使用多层视图)需要一秒钟才能返回所有行。但是,当我要求不同的行时,它需要更多的时间。 4 分钟后我停止等待。

为了让自己尽可能清晰:

select a, b from compicated_view; -- takes 1 sec (returns 6 rows)
select distinct a, b from compicated_view; -- takes at least 4 minutes

我觉得这很奇怪,但是嘿,就是这样。我猜 Oracle 在计划查询时搞砸了。现在,有没有一种方法可以强制 Oracle 首先完成没有 distinct 的选择,然后对结果执行“select distinct *”?我查看了优化器提示,但找不到任何关于提示应用 distinct 的顺序的信息(显然,这是我第一次优化查询:-/)。

我在 Oracle 10g EE 上使用 Oracle SQl Developer。

【问题讨论】:

  • 您确定在 1 秒的运行中返回了“所有”行吗?与 SQL 开发人员合作时,引擎将返回部分记录集并显示它。当您向下滚动时,更多记录变为可用并被修改显示。因此,您可以看到记录已返回,但实际上只有一个子集。
  • @xQbert 是的,只有 6 行。
  • 两者的执行计划是什么样的?
  • 它非常大,执行计划的 HTML 导出有 335 kB 用于带有 distinct 的查询,338 kB 用于没有 distinct 的查询。

标签: oracle query-optimization distinct


【解决方案1】:

试试:

SELECT DISTINCT A,B FROM (
   SELECT A,B FROM COMPLICATED_VIEW 
   WHERE rownum > 0 );

这会强制实现子查询并防止视图合并/谓词推送,并可能更改视图的原始计划。

你也可以试试 NO_MERGE 提示:

SELECT /*+ NO_MERGE(alias) */ 
     DISTINCT a,b
FROM ( 
   SELECT a,b FROM COMPLICATED_VIEW 
) alias

【讨论】:

  • rownum 技巧起作用的地方。 NO_MERGE 没有帮助。感谢您的回答!
【解决方案2】:

由于您尚未发布详细信息...请尝试以下操作:

SELECT DISTINCT A,B
FROM
(SELECT A,B FROM COMPLICATED_VIEW);

【讨论】:

  • 试过了,也需要永远执行。你想要什么样的细节?如果您愿意,我可以在 pastebin 上发布执行计划。
  • 尝试SELECT DISTINCT A,B FROM (SELECT A,B FROM COMPLICATED_VIEW WHERE rownum > 0 );,这会强制实现子查询并防止视图合并/谓词推送,并可能更改视图的原始计划。你也可以试试 NO_MERGE 提示:SELECT /*+ NO_MERGE(alias) */ DISTINCT * FROM ( SELECT * FROM COMPLICATED_VIEW ) alias
  • @kordirko 禁用复杂视图合并几乎可以肯定是正确的方法。您应该发布该评论作为答案。
猜你喜欢
  • 1970-01-01
  • 2015-11-01
  • 2022-01-05
  • 1970-01-01
  • 2021-04-16
  • 2014-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多