2014-09-22 74 views
3

在表中插入新记录时,可以有两种方法,一种是找到主键列的最大值并向其添加1或使用序列。哪种方法更好,为什么?序列vs最大主键值+ 1

如果我们通过递增表中主键列的最大值小于20,000条记录来找到下一个主键值,会产生什么影响?

谢谢。

+8

提示:尝试在多用户环境中的最高值的方法,你会发现为什么使用顺序是正确的方法。 – 2014-09-22 18:41:00

+2

我建议你使用序列。成本做一次nextval将永远低于做了最大的操作 – Aramillo 2014-09-22 18:43:31

+3

系列化(锁定造成的等待)肯定是缺点的最大主键+ 1分的方式。 – 2014-09-22 18:43:56

回答

12

问:哪种方法更好,为什么?

- 答:使用SEQUENCE对象是一种更好的方法。

MAX(id)+1方法来获得价值独特 ID是在多线程环境中,不存在并发杀破锁。这个问题不会在单用户测试中暴露出来;但使用两个不同的会话很容易证明这一点。考虑这样的操作顺序:

会话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)

为了防止两个(或更多)单独的会话返回相同的值next_id,会话必须获得排它锁它执行查询之前的表。它还需要保持该锁定,直到在将该值插入表格之前,在释放锁定之前。虽然该会话在表上保留排它锁,但其他会话不能查询或插入表中,如果其他会话尝试执行,则会阻止其他会话。 (我们不希望通过引入这种锁定来杀死数据库性能,这不是正确的方法,所以我们不打算演示如何完成。)

Oracle提供了SEQUENCE对象作为高效用于获得唯一值的方法,针对SEQUENCE对象的查询在多线程环境中是“安全的”。对于高负载下的性能,我们会增加序列的“缓存”值,即内存中可用值的数量,这样我们就可以满足更多的NEXTVAL请求,而不需要写入重做日志。

鉴于这两种选择,SEQUENCE是更好的方法。


问:什么影响,如果我们发现通过在具有小于20,000条记录表增加主键列的最大值的下一个主键值?

一个:检索索引列的最大值(也就是在一个索引的前导列的列),以及添加一个到它的查询,应该是很有效的,因为只要会话是能够获得所需的共享锁(即会话不被排他锁锁定)。)