You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 06:50:01