使用ROWNUM进行Oracle查询优化
这个问题现在没有实际意义 我重新计算了表格中的统计数据,添加了新的指数,并重新分析了现有指数.这完全改变了我的结果,并使我的大多数发现无效.在这一点上,我发现了一个新的查询,它具有足够的性能,不需要任何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并且不会在该字段上使用索引. (编辑:上饶站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |