应调大CACHE缓解锁争用、设INCREMENT BY打散写入热点;CACHE 10~100平衡性能与ID丢失风险,INCREMENT BY配合索引优化写入分布,二者正交配置且需全链路审视序列使用场景。
为什么要调 CACHE 和 INCREMENT BY?
PostgreSQL 的 SEQUENCE 在高并发 INSERT 场景下,常因频繁访问序列对象引发锁争用——本质是所有会话抢同一个序列的“下一个值”,形成单点热点。默认 CACHE 1 每次只预取一个值,每插一行就要加一次序列锁;而 INCREMENT BY 若设为 1,又会让相邻 ID 过于集中,加剧索引页分裂或缓存局部性差的问题。
CACHE 值怎么选才不丢 ID 也不卡性能?
增大 CACHE 是最直接有效的缓解手段,但不是越大越好:
-
CACHE 10~CACHE 100是常见安全区间:100 个值一次加载进内存,可支撑百级并发插入而不明显争抢 - 风险点:数据库异常崩溃时,已分配但未使用的缓存值会永久丢失(比如
CACHE 100,最后分配了 92 个,崩了,剩下 8 个就跳过了)——只要业务不依赖“连续无空洞”的 ID,这完全可接受 - 千万别设
CACHE 10000:共享内存压力大,且重启后可能浪费大量 ID;更糟的是,某些连接池(如 PgBouncer in transaction mode)会复用序列缓存,导致跨会话 ID 错乱 - 实操建议:
CREATE SEQUENCE order_id_seq CACHE 50;
INCREMENT BY 不只是“步长”,它影响索引写入效率
单纯调大 CACHE 只能减锁,不能解决新生成 ID 集中写入同一索引页的问题。这时 INCREMENT BY 就起作用了: