在表中插入新记录时,可以有两种方法,一种是找到主键列的最大值并对其加1或使用序列。哪种方法更好,为什么?
如果我们通过增加记录少于20,000条的表中主键列的最大值来找到下一个主键值有什么影响?
谢谢。
最佳答案
问:哪种方法更好,为什么?
A: 使用 SEQUENCE
对象是一种更好的方法。MAX(id)+1
获取唯一 id 值的方法在多线程环境中被破坏,没有并发杀死锁定。这个问题在单用户测试中不会暴露;但是使用两个不同的 session 很容易证明这一点。考虑以下操作序列:
session 1:SELECT MAX(id)+1 AS next_id FROM mytable
--> 42
第 2 节:SELECT MAX(id)+1 AS next_id FROM mytable
--> 42
第 1 节:INSERT INTO mytable (id) VALUES (42)
第 2 节:INSERT INTO mytable (id) VALUES (42)
为了防止两个(或更多)单独的 session 返回相同的 next_id
值, session 有必要在执行查询之前获得表上的排他锁。它还需要持有该锁,直到将具有该 next_id
值的行插入到表中,然后再释放锁。当该 session 持有表的排他锁时,没有其他 session 可以查询或插入到表中,如果其他 session 尝试这样做,它们将被阻塞。 (我们不想通过引入这种锁定来降低数据库性能,这不是正确的方法,所以我们不会演示如何做到这一点。)
Oracle 提供 SEQUENCE
对象作为获取唯一值的有效方法,并且在多线程环境中对 SEQUENCE 对象的查询是“安全的”。为了在高负载下提高性能,我们会增加序列的“缓存”值,即内存中可用值的数量,这样我们就可以满足更多 NEXTVAL 请求而无需写入重做日志。
鉴于这两个选项,SEQUENCE
是更好的方法。
Q:在20000条记录以下的表中,通过增加主键列的最大值来找到下一个主键值有什么影响?
A: 检索索引列(索引中的前导列的列)的最大值并向其添加一个的查询应该是非常有效的,只要 session 能够获得所需的共享锁(也就是说, session 不会被排他锁阻塞。)
关于oracle - 序列 vs 最大主键值 + 1,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25980960/