子选择(而不是数字常量)会使优化变差

时间:2014-11-05 13:52:54

标签: sql oracle select exadata

我的问题类似于To subselect or not to subselect?,但我想继续使用现有的两个视图(因此我不想将子视图直接移动到视图逻辑中)。

(1.5秒)

SELECT h.n
FROM   v_headers h 
WHERE  h.n >= (select 3000 from dual);

直接使用subselect中的值时,查询快速

SELECT h.n
FROM   v_headers h 
WHERE  h.n >= 3000;

更多细节:n不是唯一的,它的值在0到4000之间;对于每个n存在大约50行。来自不同行的11个值沿着n轴旋转到列中。

有没有提取视图后面的选择(或修改表)的解决方案?优化器暗示可能吗?

首先是慢速的,第二个是快速的: enter image description here

LE:我简化了查询。


由于@ nop77svk,简化的查询工作得很快。更复杂的查询还没有(还):

快速

with xyz$ as (select 3986 as n from dual)
SELECT h.hw_number
  FROM xyz$ X
  JOIN v_headers h
    ON h.hw_number >= x.n

缓慢(并且仍然有些简化):

with xyz$ as ((SELECT nvl(MAX(n), 0) AS n
           FROM (SELECT h.hw_number AS n,
                        Rank() OVER(ORDER BY h.hw_number DESC) rnk
                   FROM x_data h
                  GROUP BY h.hw_number)
          WHERE rnk = 50))
SELECT h.hw_number
  FROM xyz$ X
  JOIN v_headers h
    ON h.hw_number >= x.n;

new query


有关视图v_headers的更多详细信息:

WITH s AS
(
       SELECT a.n,
              b.col_name,
              a.value,
              b.col_id
       FROM   qa_data a
       JOIN   column_def b
       ON     b.col_id = a.col_id
       WHERE  b.master_dynamic_data = 'M' )
SELECT   "n","c1","c2","c3","c4","c4","c5","c6","c7","c8","c9","c10"
FROM     s PIVOT( Max(value) 
                keep(dense_rank first ORDER BY col_id) FOR col_name IN (
                     'c1' c1,
                     'c2' c2,
                     'c3' c3,
                     'c4' c4,
                     'c5' c5,
                     'c6' c6,
                     'c7' c7,
                     'c8' c8,
                     'c9' c9,
                     'c10' c10,
                     'c11' c11) )

COLUMN_DEF

  • 72行
  • 57行,包含master_dynamic_data =' M'
  • column_def.col_id:唯一1..100(有空白)
  • column_def.col_name:c1,c2,c3,...(实际上是20个字符而不是' cx')

qa_data:

  • 450k行
  • 每个qa_data.n的平均行数为112行。 (n是1到4000)
  • qa_data.value的平均长度为18个字符

1 个答案:

答案 0 :(得分:1)

在简化版中......

SELECT --+ leading(X) use_hash(H)
    H.n
FROM (select 3000 as n from dual) X
    JOIN v_headers H
        ON H.n >= X.n
;

... >= 3000谓词被正确解析为访问谓词,这会导致Exadata存储索引启动。

但是,在完整版中,必须强制将谓词传播到内部视图,这似乎不会发生。快速检查测试设置显示,将这样的谓词(对于计算值,而不是常量值)传播到连接视图运行正常,但将谓词传播到透视连接视图则不会。

当使用预先计算n的值而不是使用内联视图的(确定性)函数时,情况也是如此 - 谓词不会被推送到透视连接视图(在12.1.0.2上尝试过) )。

看到10053事件跟踪文件以了解发生了什么将会很有趣。 (为读者做作业。; - ))