如何在PostgreSQL中保留主键约束但禁止自动创建主键索引?
问题解答
首先纠正你脚本中的两处语法错误:
CREATE TABLE IN NOT EXISTS应为CREATE TABLE IF NOT EXISTS- 列定义中的冒号需改为逗号,修正后的完整脚本如下:
CREATE TABLE IF NOT EXISTS table_name ( entity_key BYTEA NOT NULL, name TEXT NOT NULL, val BYTEA, ts TIMESTAMPTZ, PRIMARY KEY(entity_key, name) ); CREATE INDEX IF NOT EXISTS table_name_ek ON table_name (entity_key);
核心结论
PostgreSQL 无法创建不带索引的主键。主键约束的唯一性与非空性强制依赖索引实现——没有索引的话,数据库无法高效验证主键唯一性,每次插入/更新都需要全表扫描,这对于90亿条数据的表来说完全不具备可操作性。
针对你的场景的优化方案
你的主键索引占用450GB且更新开销大,核心问题在于存在冗余索引,可以通过以下方式优化:
删除单独的
entity_key索引:主键索引(entity_key, name)是前缀索引,完全可以满足基于entity_key的查询需求(PostgreSQL会利用前缀匹配使用该索引)。单独创建的table_name_ek索引属于冗余,会额外占用存储空间并增加更新时的索引维护成本。执行DROP INDEX IF EXISTS table_name_ek;即可删除该冗余索引。定期重建主键索引:大量更新操作会导致索引产生碎片,引发索引膨胀。可以通过重建索引来回收空间:
REINDEX INDEX table_name_pkey; -- 替换为实际的主键索引名,通常为表名_pkey若表数据量极大,可使用
CONCURRENTLY参数避免锁表:REINDEX INDEX CONCURRENTLY table_name_pkey;考虑表分区:90亿条数据属于超大规模表,按
entity_key或ts进行分区后,每个分区的索引大小会显著减小,更新操作的范围也会被限制在单个分区内,大幅降低索引维护开销。
内容的提问来源于stack exchange,提问作者mascai
相关产品推荐
相关产品推荐

