oracle的rownum为什么能做到快速查询结果

我有一个百万数量级的表,row_id是主键

select * from history a order by a.row_id desc;

这样执行查询结果非常的慢,查看执行计划,用到了全表扫描。
但是执行以下查询 ,简称sql2

select * from (
select a.row_id,rownum rn from history a order by a.row_id desc )t
where rownum<20;

速度非常的快,查看执行计划,是直接用到了主键索引。
通过
select max(row_id) from history;
对对上结果进行了验证,发现查询结果是没问题的。
我想问的是,rownum在执行过程中究竟是进行了怎样的优化?
按照我的理解,sql2中的查询应该是对子查询内部的所有数据查询出来,然后进行排序,然后将结果集再取前20行。不然查询结果怎么会是正确排序的结果呢。
请大佬们赐教。
------------------------------------------------------------补充
我再次进行了测试

select * from (
select a.row_id,rownum rn from history a
where a.create_date >sysdate -30
 order by a.row_id desc )t
where rownum<20;

create_date是普通索引

select * from (
select a.row_id,rownum rn from history a
where a.row_id >10
 order by a.create_date desc )t
where rownum<20;

这第二个sql也是光速返回结果。
我的猜测是由于主键row_id是顺序存储的,所以当没有查询条件的时候,cbo会直接从索引开头位置取20行。当查询条件为主键时,同理。查询条件为普通索引时,就需要先进行查询再排序了,这样效率就低了。

阅读 2.4k
1 个回答

使用索引是查询优化的一种,一般为优化查询都会在必要列中添加索引
所以当索引为主键时会进行唯一性扫描,而当索引为普通索引会自动进行范围扫描,从而改变查询效率

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题