我们有下表的定义
CREATE TABLE Log
(
LogId serial not null,
JobId integer not null,
Time timestamp without time zone,
LogText text not null,
primary key (LogId)
);
create index log_name_idx on Log (JobId);
LogId 已达到串行最大值(20 亿) 我们必须手动删除较旧的条目并清理表,因为我们从 PostgreSQL 日志中收到以下错误
##ERROR: integer out of range ##STATEMENT: INSERT INTO Log (JobId, Time, LogText) VALUES .....
整数指的是 LogId,因为它已达到最大正整数/serial4 值 2,147,483,647。
现在我们遇到以下问题: logid 列(也是主键)的最新条目最大为 (2,147,483,647)。 我们希望重新创建主键列的条目,以便它与该表的行数匹配。这个数字是 953,811,856。仍然很大,但如果这个问题得到解决,我们可以自动化删除和清理表的过程。
在删除和真空之后,几乎一半的条目及其匹配的主键被删除,如果您愿意,我们希望“重新对齐”主键与表的其余剩余值,这意味着我们希望表中最旧的剩余条目的 LogID 字段上的数字为 1,并将其增加到最新的行条目,达到 953811856。
请注意,LogId 是串行数据类型,我不知道为什么我们从日志中得到的错误引用了一个整数。最好的客人,因为整数和序列4具有相同的最大值。
我们尝试在测试环境中将串行序列更改为 1,即使这有效并且在表中添加了新条目,最终也会在主键中创建重复条目,因为我们尚未完全删除所有先前条目来自 LogId 列。
切换到
bigserial
/bigint generated by default as identity
- 这将使您的限制达到 9223372036854775807
。 演示:
alter table log alter column LogId type bigint;
select pg_get_serial_sequence('public.log','logid');
alter sequence public.log_logid_seq as bigint;
identity
:
alter table log alter column LogId type bigint;
alter table log alter column LogId drop default;
alter table log alter column LogId
add generated by default as identity;
与完全更改类型或添加另一列来构建多列主键相比,这里的好处是指向该表的所有外键列保持不变。您可以查找它们并在另一步骤中切换到 bigint。
serial
仅意味着int
您希望Postgres为其创建和维护序列 - 它不是真正不同的类型,所以您的猜测
最佳猜测,因为integer 和serial4 具有相同的最大值。
是对的。
bigserial
的情况也类似:同样的事情,但是 bigint
。
定期
vacuum
、重新编号和倒带序列的想法听起来很危险,因为它必须级联各处的引用。任何外部引用或内部弱链接(用于保存外键但没有 references
约束的列)都会中断。切换到 bigint
,您可以完整保留所有标识符和对它们的所有引用。