我正在创建一个在SQL Server和PostgreSQL上运行的应用程序,所以我问这两个问题。
每当您创建一个唯一的主键(使用序列或自动增量类型的东西)并且您击中超过40亿条记录(32位)时会发生什么?我并不是说我们的表将有40亿条记录,而是因为RID只增加而创建了40亿条记录。因此,即使我删除了39亿条这些记录,我的RID仍然在40亿的范围内。那会发生什么?是将精度提高到64位还是将其翻转为0或者只是吐出一个非常严重的错误?我是否应该担心即使是64位RID也可能最终溢出?
另外,我该如何对抗这个?是否有某种清理选项或工具?我是否只需要创建自己的东西,每年左右完全重建表以获得一致的RID? (因此也触及很多其他使用这些RID的表都是外键)
答案 0 :(得分:3)
默认情况下,PostgreSQL会出错,而不是溢出:
# create sequence willyouwrap;
CREATE SEQUENCE
# select setval('willyouwrap', 9223372036854775807);
setval
---------------------
9223372036854775807
(1 row)
# select nextval('willyouwrap');
ERROR: nextval: reached maximum value of sequence "willyouwrap" (9223372036854775807)
来自文档:
序列基于bigint算法,因此范围不能超过8字节整数的范围(-9223372036854775808至9223372036854775807)。在一些较旧的平台上,可能没有编译器支持8字节整数,在这种情况下,序列使用常规整数运算(范围-2147483648到+2147483647)。
但是,你可以让它循环:
CYCLE选项允许序列在分别通过升序或降序达到maxvalue或minvalue时回绕。如果达到限制,则生成的下一个数字将分别为minvalue或maxvalue。
如果指定NO CYCLE,则在序列达到其最大值后对nextval的任何调用都将返回错误。如果未指定CYCLE或NO CYCLE,则默认为NO CYCLE。
不要打架。花费额外的字节并保持简单。与拥有更大的密钥空间相比,您更有可能后悔添加额外的复杂性和/或维护任务层。
答案 1 :(得分:1)
在SQL Server上:它取决于RID列的类型。内部IDENTITY可以递增,但无法分配到stoarge列:
CREATE TABLE [t1] (
[tid] int IDENTITY (2147483647, 1) NOT NULL
, name varchar(1)
) ON [PRIMARY]
GO
insert into t1(name) values('1')
insert into t1(name) values('1')
这会触发错误:
Msg 8115, Level 16, State 1, Line 2
Arithmetic overflow error converting IDENTITY to data type int.
Arithmetic overflow occurred.
但是具有足够存储空间的数字列会增加正常:
CREATE TABLE [t1] (
[tid] numeric(38,0) IDENTITY (2147483647, 1) NOT NULL
, name varchar(1)
) ON [PRIMARY]
GO
insert into t1(name) values('1')
insert into t1(name) values('1')
同样,bigint将在2 ^^ 63-1:
超过CREATE TABLE [t1] (
[tid] bigint IDENTITY (9223372036854775807, 1) NOT NULL
, name varchar(1)
) ON [PRIMARY]
GO
insert into t1(name) values('1')
insert into t1(name) values('1')
但是具有足够存储空间的数字列将成功:
CREATE TABLE [t1] (
[tid] numeric(38,0) IDENTITY (9223372036854775807, 1) NOT NULL
, name varchar(1)
) ON [PRIMARY]
GO
insert into t1(name) values('1')
insert into t1(name) values('1')