Sql 选择“n”表中上次插入的记录-oracle
表具有从序列生成的代理主键。不幸的是,这个序列用于为其他一些表生成键,我没有设计它,也不能更改它 选择Oracle中最后n条插入记录的最快方法是什么,按id按降序排列最后一条插入在顶部 n是一个相对较小的数字——显示在页面上的记录数——可能不大于50 表现在有30.000.000条记录,每天有10000-15000条新记录 数据库是oracle10g 编辑: 在回答一条评论时:这个问题的动机是执行查询计划:Sql 选择“n”表中上次插入的记录-oracle,sql,oracle,oracle10g,Sql,Oracle,Oracle10g,表具有从序列生成的代理主键。不幸的是,这个序列用于为其他一些表生成键,我没有设计它,也不能更改它 选择Oracle中最后n条插入记录的最快方法是什么,按id按降序排列最后一条插入在顶部 n是一个相对较小的数字——显示在页面上的记录数——可能不大于50 表现在有30.000.000条记录,每天有10000-15000条新记录 数据库是oracle10g 编辑: 在回答一条评论时:这个问题的动机是执行查询计划: select * from MyTable order by primarykeyf
select * from MyTable order by primarykeyfield desc
select * from (select * from arh_promjene order by promjena_id desc) x
where rownum < 50000000
执行计划是:
---------------------------------------------
| Id | Operation | Name |
---------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | SORT ORDER BY | |
| 2 | TABLE ACCESS FULL| MyTable |
---------------------------------------------
我很惊讶Oracle在排序字段上有索引的情况下想要执行全表扫描和排序
来自接受答案的查询使用索引并避免排序
编辑2:
重新。APC的评论:排序是令我惊讶的一部分。我预计Oracle将使用索引按预期顺序检索行。查询的执行计划:
select * from MyTable order by primarykeyfield desc
select * from (select * from arh_promjene order by promjena_id desc) x
where rownum < 50000000
使用索引而不是完全表访问和排序通知条件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)
Oracle为这两个返回相同结果集的查询创建不同的执行计划,这对我来说是不寻常的
编辑3:
关于阿莫克的评论:
甲骨文公司不知道5000万美元是多少
大于行数。当然
它有统计数据,但也可能是
旧的和错误的-甲骨文永远不会
允许自己发送错误的
结果只是因为统计数据是正确的
错
你确定吗?在9之前的Oracle版本中,建议不时手动刷新统计信息。自版本10起,Oracle自动更新统计信息。如果Oracle不使用统计数据进行查询优化,那么统计数据有什么用处 使用ROWNUM:
请注意,rownum是在对子查询进行排序之前应用的,这就是为什么您需要两个嵌套查询,否则您只会得到n个随机行。它的查看次数会比更新次数多吗?保留最后N个插入行的ID的另一个表如何?使用触发器从该表中删除最小的ID,并使用当前插入行添加新行
现在有一个表记录最后N个插入行的ID。任何时候你想要N,只要把它加入主表就行了。如果N发生变化,请选择最大值,然后在。。。当然,您可能会发现应用程序的维护速度不太快。此表的维护可能会抵消任何性能提升如果您不知道字段名称或表名以外的任何内容,这可能会对您有所帮助
select * from (
select * from(
select rownum r,student.* from student where rownum<=(
select max(rownum) from student
)
) order by r desc
) where r<=10;
尝试执行索引描述提示
select /*+ index_desc(MyTable,<PK_index>) */ * from MyTable order by primarykeyfield desc
在没有严格递增字段的情况下,也可以使用系统更改数作为近似值
select * from (select * from student order by ORA_ROWSCN desc) where rownum<10
注意:这并不准确,因为Oracle每个块(而不是每行)只记录一个SCN。此外,它似乎还进行了完整的表扫描——可能oracle不够聪明,无法优化这种排序。因此,这对于生产应用来说可能不是一个好主意。这意味着博克是可排序的。。。这和OP兼容吗?很可能是这样,但如果是这样的话,OP会问这样一个简单的问题,那就很奇怪了。如果我们把bork作为OP提到的序列生成主键,假设它是单调递增的,那么这个查询就行了。它行得通,但如果数据很大,它会选择和排序数百万条记录,只取前10条,很遗憾,我不能像mssql那样在短时间内获得它们的最后10条记录。没有其他方法吗?@TMoon-对于大多数表,您只需按PK或索引日期列排序,然后使用top子句即可。被迫以这种方式使用rownum是原始问题中一些非常糟糕的设计决策的产物。为什么不幸的是,该序列也用于其他表?查询检索最后n条插入的记录并不重要,因为Oracle从未将序列视为无间隙。所以你不能在max-n和max之间做一个简单的where-id。你的查询会选择所有行的所有列。为什么您会对Oracle进行完整的表扫描感到惊讶?否则它将如何获取数据以满足该查询?Oracle不知道50M大于行数。当然,它有统计数据,但这些数据可能是旧的和错误的——而且甲骨文永远不会因为统计数据是错误的而允许自己提供错误的结果。