zen*_*dar 6 sql oracle oracle10g
表具有从序列生成的代理主键.不幸的是,这个序列用于为其他一些表生成密钥(我没有设计它,我也无法改变它).
n在Oracle中选择最后插入记录的最快方法是什么,按ID按降序排列(最后插入到顶部)?
n 是一些相对较小的数字 - 页面上显示的记录数 - 可能不超过50.
表现在有30.000.000条记录,每天有10-15,000条新记录.
数据库是Oracle 10g.
编辑:
回答一条评论:这个问题的动机是查询的执行计划:
select * from MyTable order by primarykeyfield desc
Run Code Online (Sandbox Code Playgroud)
执行计划是:
---------------------------------------------
| Id | Operation | Name |
---------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | SORT ORDER BY | |
| 2 | TABLE ACCESS FULL| MyTable |
---------------------------------------------
Run Code Online (Sandbox Code Playgroud)
我很惊讶Oracle希望在排序字段上有索引时执行全表扫描和排序.
来自已接受答案的查询使用索引并避免排序.
编辑2:
Re.APC的评论:排序是让我感到惊讶的一部分.我预计Oracle会使用index来按预期顺序检索行.查询执行计划:
select * from (select * from arh_promjene order by promjena_id desc) x
where rownum < 50000000
Run Code Online (Sandbox Code Playgroud)
使用索引而不是全表访问和排序(通知条件rownum < 50.000.000- 这比表中的记录数量多,Oracle知道它应该从表中检索所有记录).此查询将所有行作为第一个查询返回,但具有以下执行计划:
| Id | Operation | Name |
-------------------------------------------------------
| 0 | SELECT STATEMENT | |
|* 1 | COUNT STOPKEY | |
| 2 | VIEW | |
| 3 | TABLE ACCESS BY INDEX ROWID| MyTable |
| 4 | INDEX FULL SCAN DESCENDING| SYS_C008809 |
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(ROWNUM<50000000)
Run Code Online (Sandbox Code Playgroud)
对我来说,Oracle正在为这两个基本上返回相同结果集的查询创建不同的执行计划.
编辑3: Re Amoq的评论:
Oracle不知道50M大于行数.当然,它有统计数据,但它们可能是旧的和错误的 - 并且Oracle永远不会仅仅因为统计数据错误而允许自己传递错误的结果.
你确定吗?在最多9个Oracle版本中,建议不时手动刷新统计信息.从版本10开始,Oracle会自动更新统计信 如果Oracle不将其用于查询优化,那么统计数据的用途是什么?
Don*_*nie 15
用途ROWNUM:
select
*
from
(
select
*
from
foo
order by
bork
) x
where
ROWNUM <= n
Run Code Online (Sandbox Code Playgroud)
请注意,在排序子查询之前rownum应用,这就是您需要两个嵌套查询的原因,否则您将获得随机行.n