Jas*_*ker 11 sql oracle row-number oracle10g
我有一个SQL查询,看起来像这样:
SELECT * FROM(
SELECT
...,
row_number() OVER(ORDER BY ID) rn
FROM
...
) WHERE rn between :start and :end
Run Code Online (Sandbox Code Playgroud)
从本质上讲,正是ORDER BY部分减慢了速度.如果我要删除它,EXPLAIN成本会下降一个数量级(超过1000倍).我试过这个:
SELECT
...
FROM
...
WHERE
rownum between :start and :end
Run Code Online (Sandbox Code Playgroud)
但这并没有给出正确的结果.有没有简单的方法来加快速度?或者我是否需要花更多时间使用EXPLAIN工具?
Qua*_*noi 12
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
Run Code Online (Sandbox Code Playgroud)
此查询将使用 COUNT STOPKEY
还要么确保您column不可为空,要么添加WHERE column IS NOT NULL条件.
否则,索引不能用于检索所有值.
请注意,如果ROWNUM BETWEEN :start and :end没有子查询,则无法使用.
ROWNUM总是最后分配并最后检查,这种方式ROWNUM总是按顺序排列.
如果您使用ROWNUM BETWEEN 10 and 20,满足所有其他条件的第一行将成为返回,临时分配ROWNUM = 1和未通过测试的候选者ROWNUM BETWEEN 10 AND 20.
然后下一行将是候选,分配ROWNUM = 1和失败等,因此,最后,根本不会返回任何行.
这应该通过将ROWNUM's'放入子查询来解决.
看起来像是一个分页查询给我.
从这篇ASKTOM文章(约90%的页面):
您需要按照这些分页查询的唯一内容进行排序,以便每次都确定性地为行分配ROW_NUMBER.
你的查询也不在同一个地方,所以我不确定比较一个和另一个的成本有什么好处.