概述
大多数业务表都存在热数据子集:未完成订单、活跃会话、未删除记录。全量索引会为每一行付出写入成本,并占用本应留给热数据的内存。部分索引只包含满足谓词的行,因此体积更小、更容易常驻缓存、维护成本更低。
步骤
- 确认应用查询的谓词,确保规划器能够匹配:
EXPLAIN SELECT id FROM orders
WHERE tenant_id = 42 AND status = 'open'
ORDER BY created_at DESC LIMIT 20;
- 使用相同谓词并发建索引,并按查询的排序方式排列列:
CREATE INDEX CONCURRENTLY idx_orders_open_tenant
ON orders (tenant_id, created_at DESC)
WHERE status = 'open';
- 执行
ANALYZE orders;后用EXPLAIN (ANALYZE, BUFFERS)确认走的是部分索引。 - 对比部分索引与全量索引的大小,确认差异符合预期。
验证
预期执行计划显示 Index Scan using idx_orders_open_tenant,共享缓冲区读取远低于全表扫描,部分索引体积通常小一个数量级。检查 pg_index.indisvalid 为 true,避免并发建索引失败留下无效索引。
注意事项
- 查询必须包含与索引完全一致的谓词,否则无法使用部分索引。
- 若同时存在查询全部状态的路径,仍需保留全量索引。
CREATE INDEX CONCURRENTLY不能在事务中执行,耗时长且需要两次表扫描,应避开高峰。- 状态机新增取值后要同步检查索引谓词,否则新状态会退化为全表扫描。