加入收藏 | 设为首页 | 会员中心 | 我要投稿 上饶站长网 (https://www.0793zz.com.cn/)- 数据库平台、视觉智能、智能搜索、决策智能、迁移!
当前位置: 首页 > 站长百科 > 正文

使用ROWNUM进行Oracle查询优化

发布时间:2021-01-12 20:12:39 所属栏目:站长百科 来源:网络整理
导读:这个问题现在没有实际意义 我重新计算了表格中的统计数据,添加了新的指数,并重新分析了现有指数.这完全改变了我的结果,并使我的大多数发现无效.在这一点上,我发现了一个新的查询,它具有足够的性能,不需要任何ROWNUM技巧. 此外,我认为值得指出的是,下面的查询

这个问题现在没有实际意义

我重新计算了表格中的统计数据,添加了新的指数,并重新分析了现有指数.这完全改变了我的结果,并使我的大多数发现无效.在这一点上,我发现了一个新的查询,它具有足够的性能,不需要任何ROWNUM技巧.

此外,我认为值得指出的是,下面的查询,如所写,不能保证给出我想要的结果.将DISTINCT添加到中间查询可能会破坏我尝试在最里面的查询中应用的顺序.在实践中,这没有发生,但我不能依赖于此.

原始问题

我写了一个查询,当我输入一个假的ROWNUM检查时,它似乎表现得更好:

SELECT * FROM
  (
    SELECT DISTINCT * FROM 
    ( 
      SELECT TransactionID FROM WOWDev.QueryLog WHERE UPPER(UserName)=UPPER('xyz') AND TransactionID IS NOT NULL ORDER BY TransactionID DESC
    ) 
    WHERE ROWNUM<=1e100 -- fake ROWNUM check! this gets us on the fast path
  )
  WHERE ROWNUM<=50

这是优化器计划.

SELECT STATEMENT,GOAL = ALL_ROWS           38025   50  650
 COUNT STOPKEY                  
  VIEW  JSTILES     38025   801 10413
   SORT UNIQUE NOSORT           38025   801 3204
    COUNT STOPKEY                   
     VIEW   JSTILES     38024   801 3204
      TABLE ACCESS BY INDEX ROWID   WOWDEV  QUERYLOG    38024   545694  9276798
       INDEX FULL SCAN DESCENDING   WOWDEV  IX_QUERYLOG_TID 1263    212704

如果我注释掉了假的ROWNUM检查,那么查询突然崩溃并变得慢得多(以及成本为5倍).

SELECT STATEMENT,GOAL = ALL_ROWS           204497  50  650
 COUNT STOPKEY                  
  VIEW  JSTILES     204497  34865   453245
   SORT GROUP BY STOPKEY            204497  34865   592705
    INDEX FAST FULL SCAN    WOWDEV  IX_QUERYLOG_USER_TID    204462  545694  9276798

显然,这也是一个完全不同的指数(一个显然不适合它).

如果我自然地简化查询并删除所有冗余,我们会得到一个与穷人版本类似的执行计划,同样性能也差.

SELECT * FROM 
(
  SELECT DISTINCT TransactionID
          FROM WOWDev.QueryLog
         WHERE UPPER(UserName) = UPPER('xyz')
           AND TransactionID IS NOT NULL
         ORDER BY TransactionID DESC
)
WHERE ROWNUM <= 50

解释如下:

SELECT STATEMENT,GOAL = ALL_ROWS           207527  50  650
 COUNT STOPKEY                  
  VIEW  JSTILES     207527  34865   453245
   SORT UNIQUE STOPKEY          207491  34865   592705
    INDEX FAST FULL SCAN    WOWDEV  IX_QUERYLOG_USER_TID    204462  545694  9276798

如下所示,我尝试用ROWNUM> 0替换我的ROWNUM< = 1e100,这也达到了快速路径,但计划略有不同:

SELECT STATEMENT,GOAL = ALL_ROWS           38025   50  650
 COUNT STOPKEY                  
  VIEW  JSTILES     38025   801 10413
   SORT UNIQUE NOSORT           38025   801 3204
    COUNT                   
     FILTER                 
      VIEW  JSTILES     38024   801 3204
       TABLE ACCESS BY INDEX ROWID  WOWDEV  QUERYLOG    38024   545694  9276798
        INDEX FULL SCAN DESCENDING  WOWDEV  IX_QUERYLOG_TID 1263    212704

谁能解释这种行为?是否有更清洁,更少hacky的方式让Oracle走上快车道?

解决方法

这不一定是正确的答案,但….

我用过ROWNUM>过去0强制数据“物化”.

这反过来允许查询处理器获得正确的基数.

例如,如果查询规划器认为特定谓词只返回一行,它通常会在其上使用笛卡尔连接.如果数据实际上不是一行而是很多,则笛卡尔连接会导致大量行和大量不正确的处理.添加ROWNUM> 0迫使它在评估ROWNUM>之前评估每一行的rownum. 0,有效地强制数据的实现

虽然这看起来不是这个问题.

也许是因为数据的传播,实现起来更快,然后搜索表而不是首先检查索引.

在该计划转储中是否有办法解决谓词的应用位置?

很遗憾你必须UPPER这个领域,因为它使它不具有sargeable并且不会在该字段上使用索引.

(编辑:上饶站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读