只索引一部分数据
PostgreSQL 的部分索引只索引满足条件的那部分行:过滤条件固定、热点数据占比低的查询收益最大,比如只给未完成订单建索引。索引体积更小、维护成本更低,命中前提是查询的过滤条件能被优化器论证出「蕴含索引谓词」。
基本信息
| 适用平台 | PostgreSQL |
|---|---|
| 语法 | CREATE INDEX 名 ON 表 (列) WHERE 谓词 |
| 原理 | 索引只覆盖满足谓词的行,体积小、维护成本低 |
| 命中前提 | 查询谓词能被论证蕴含索引谓词 |
| 典型场景 | 未完成、未删除、指定类型的数据子集 |
典型使用场景
- 只给未完成订单建索引,跳过海量已完成数据
- 逻辑删除场景只索引未删除行
- 按类型区分的热点子集
- 降低宽表上索引的体积与写成本
- 替代对全表一刀切建索引的粗放做法
示例
示例
-- 只给待处理订单建索引
CREATE INDEX idx_orders_pending_created
ON orders (created_at)
WHERE status = 'pending';
-- 命中:查询条件包含 status = 'pending'
SELECT * FROM orders
WHERE status = 'pending' AND created_at > now() - interval '1 day';
-- 不命中:查询里没有 status = 'pending' 这个条件
SELECT * FROM orders WHERE created_at > now() - interval '1 day';命中与不命中
| 查询写法 | 能否用部分索引 | 原因 |
|---|---|---|
| 带 status = 'pending' 与时间范围 | 可以 | 谓词蕴含索引谓词 |
| 只带时间范围 | 不能 | 条件推不出索引谓词 |
| 用 IN 列出多个状态 | 视情况 | 需要优化器能论证谓词关系 |
| 用不等于某状态 | 通常不能 | 不等条件推不出等价谓词 |
| 查询谓词更宽松 | 不能 | 索引覆盖范围更窄 |
部分索引的价值来自「谓词能被推导」:查询端少写那个条件索引就完全用不上,排查慢查询时先看查询谓词与索引谓词是否对得上。
为状态频繁变化的数据建部分索引要谨慎:行在谓词内外进进出出,索引与统计都要跟着维护,写入成本未必划算。