用途:把 Postgres 当作数据契约的“引擎”来处理,覆盖索引、EXPLAIN、事务、锁、JSONB、RLS 和连接池。适用于建模表、排查慢查询、处理隔离与迁移 SQL 等。ORM 类技能(database-prisma、database-drizzle、golang-sqlc、sqlx)负责生成 SQL,本技能负责底层引擎;向量用 pgvector,Scylla 建模不在此处理。需保留项目现有 Postgres(版本、扩展、托管或自建),不因技能存在就换引擎。
核心规则:多租户下每条产品查询都要带租户/归属的 WHERE;迁移要版本化且向前安全,已上生产的迁移不可再改;加索引前先用 EXPLAIN (ANALYZE, BUFFERS);在应用或角色上设置连接池与 statement_timeout / lock_timeout,避免无限连接;组合写入放在同一事务,不用无 unique/锁的 check-then-insert。
索引:btree 用于等值、范围、同前缀 ORDER BY;GIN 用于 JSONB、数组、FTS(tsvector);GiST/SP-GiST 用于范围、地理、排他;部分索引用于 WHERE deleted_at IS NULL 等热子集;复合索引顺序按最具选择性过滤加排序。不服务 WHERE/ORDER BY 的索引是写入负担,unique 应建在业务不变量而非仅 id,高频 join/delete 的多侧建 FK 索引。
事务与锁:隔离级别随项目(通常 READ COMMITTED),仅当领域依赖时才用 SERIALIZABLE;修改聚合前用 SELECT … FOR UPDATE,worker 可用 skip locked;热点路径避免表锁,重 DDL 在团队允许时用 CONCURRENTLY;死锁靠稳定加锁顺序,只对 40001/死锁重试。
JSONB 与文本:形式不稳定或作信封时用 JSONB,常过滤字段仍建列;JSON 需不变量时用 CHECK 或生成列;FTS 用生成的 tsvector 加 GIN,并注意 locale 配置。RLS 在 Postgres 作为最后防线时启用,策略保持简单;应用已在 SQL 过滤时不必无主地重复 RLS;应用不用超级用户,权限最小化,迁移用专用角色。
连接池与运维:池按实例尺寸配置,PgBouncer transaction 模式下注意预处理语句;API 查询设 statement_timeout,长任务用更大超时和独立角色;依赖 autovacuum,高峰期不做 VACUUM FULL;备份/PITR 由提供方负责,部署时先迁移后启动应用。反模式包括 SELECT * 后在应用过滤、热列表深 offset(应改游标/keyset)、盲目给每列建索引、把整个关系领域塞进 JSONB、巨大 NOT IN(应改 NOT EXISTS/反连接)。完成标准:被改查询有索引或 EXPLAIN 支撑、SQL 含租户、不变量有 unique、组合写入有事务、角色或应用有时限、schema 变更配新迁移。