我怎么可以加速row_number在Oracle?
-
05-07-2019 - |
题
我有一个SQL query,看起来是这样的:
SELECT * FROM(
SELECT
...,
row_number() OVER(ORDER BY ID) rn
FROM
...
) WHERE rn between :start and :end
从本质上讲,这是为了通过部分,是减缓下来的东西。如果我们要删除它,解释,成本下降,通过一个数量级(超过1000倍).我已经试过这样的:
SELECT
...
FROM
...
WHERE
rownum between :start and :end
但是,这并没有给出正确的结果。是否有任何简单的方法来加速这个吗?或者将我必须花费更多的时间用于解释工具?
解决方案
ROW_NUMBER
是相当低效的 Oracle
.
看到这篇文章在我的博客的性能的详细信息:
为您特定的查询,我建议你来代替它 ROWNUM
和确保索引用于:
SELECT *
FROM (
SELECT /*+ INDEX_ASC(t index_on_column) NOPARALLEL_INDEX(t index_on_column) */
t.*, ROWNUM AS rn
FROM table t
ORDER BY
column
)
WHERE rn >= :start
AND rownum <= :end - :start + 1
这种查询将使用 COUNT STOPKEY
还要么确保你 column
是不可空,或者加入 WHERE column IS NOT NULL
条件。
否则,该指数不能用于检索的所有价值观。
请注意,不能使用 ROWNUM BETWEEN :start and :end
没有一个子查询。
ROWNUM
总是分配给最后一个,检查最后一个,这就是方法 ROWNUM
's总是为了没有差距。
如果你使用 ROWNUM BETWEEN 10 and 20
, 第一行,satisifies所有其他条件将成为一个候选人回返,临时分配 ROWNUM = 1
和失败的考验 ROWNUM BETWEEN 10 AND 20
.
然后下一个行将一名候选人,与分配 ROWNUM = 1
和失败等等, 所以,最后,没有行将返回。
这应该是工作把 ROWNUM
's入子查询。
其他提示
看起来像是一个分页查询。
从这篇ASKTOM文章(约90%页面):
您需要通过某种方式订购这些分页查询是唯一的,因此每次都会确定地为行分配ROW_NUMBER。
此外,您的查询不在同一个地方,因此我不确定比较其中一个的成本有什么好处。
您的ORDER BY列是否已编入索引?如果不是那个开始的好地方。
问题的一部分是“开始”到“结束”跨度有多大以及它们“存在”的位置。 假设你在表中有一百万行,并且你想要行567,890到567,900那么你将不得不忍受这样一个事实:它需要通过整个表,通过id排序几乎所有这些,并确定哪些行属于该范围。
简而言之,这是很多工作,这就是为什么优化器会给它带来高成本的原因。
索引也无法提供帮助。索引会给出订单,但充其量,它会让您在某个地方开始,然后继续阅读,直到您到达第567,900条。
如果您一次向最终用户显示10个项目,则可能值得从数据库中获取前100名,然后让应用程序将该100个项目分成10个块。
花更多时间使用EXPLAIN PLAN工具。如果您看到TABLE SCAN,则需要更改查询。
您的查询对我来说毫无意义。查询ROWID似乎在寻找麻烦。该查询中没有关系信息。这是您遇到问题的真实查询,还是您用来说明问题的示例?