为了查询Oracle中的前n行,通常使用ROWNUM。因此,以下查询似乎可以(获取最近的5个付款):
显然,对于大表来说,第一个查询效率低下的原因是INDEX FULL SCAN DESCENDING。但是我无法通过观察两个查询来区分它们的逻辑。
有人能用人类语言解释一下这两个查询之间的逻辑差异吗?
提前感谢!
select a.paydate, a.amount
from (
select t.paydate, t.amount
from payments t
where t.some_id = id
order by t.paydate desc
) a
where rownum <= 5;
但对于非常大的表格,这种方法效率很低 - 对我来说需要运行约10分钟。因此,我尝试了其他查询方式,最终找到了这个可以在不到1秒钟内运行的查询:
select *
from (
select a.*, rownum
from (select t.paydate, t.amount
from payments t
where t.some_id = id
order by t.paydate desc) a
)
where rownum <= 5;
为了了解发生了什么,我查看了每个查询的执行计划。对于第一个查询:
SELECT STATEMENT, GOAL = ALL_ROWS 7 5 175
COUNT STOPKEY
VIEW 7 5 175
TABLE ACCESS BY INDEX ROWID 7 316576866 6331537320
INDEX FULL SCAN DESCENDING 4 6
其次:
SELECT STATEMENT, GOAL = ALL_ROWS 86 5 175
COUNT STOPKEY
VIEW 86 81 2835
COUNT
VIEW 86 81 1782
SORT ORDER BY 86 81 1620
TABLE ACCESS BY INDEX ROWID 85 81 1620
INDEX RANGE SCAN 4 81
显然,对于大表来说,第一个查询效率低下的原因是INDEX FULL SCAN DESCENDING。但是我无法通过观察两个查询来区分它们的逻辑。
有人能用人类语言解释一下这两个查询之间的逻辑差异吗?
提前感谢!
rownum
不能保证与第一个版本中相同;你需要给第二个查询添加别名并引用它,或者在针对a
的查询中添加order by rownum
?虽然我不认为这会影响速度。 - Alex Poole