PostgreSQL 11能否创建包含JSON表达式的INCLUDE列索引?
问题根因
你遇到的报错是PostgreSQL的版本特性限制导致的:从PostgreSQL 11开始支持INCLUDE子句的覆盖索引,但仅支持将普通表列作为包含列,不支持表达式作为INCLUDE列,这和官方文档描述的一致,你对报错原因的判断是正确的。
第二种方案(把data->>'variantCode'作为索引键部分)的弊端
- 索引体积膨胀:B树索引的键列需要参与排序,除了存储值本身还要维护排序元数据、预留页分裂空间,相比INCLUDE仅存储值的模式,索引体积会高出20%~50%(具体取决于字段长度和数据量),会占用更多磁盘空间,也会降低内存中索引的缓存命中率。
- 写操作开销更高:每次插入、更新、删除数据时,都需要维护B树的排序结构,开销远高于INCLUDE列的写入成本,如果你的products表写操作占比较高,会明显影响整体写入性能。
- 冗余排序开销:B树索引自带排序属性,如果你的业务查询不需要按
data->>'variantCode'排序,这部分排序能力就是完全冗余的,会拖慢索引扫描的速度。
适配你的查询需求的最优方案
你的目标查询是按data->>'variantCode'分组聚合product_sku,不需要调整表结构,直接创建以下表达式索引即可实现索引仅扫描:
CREATE INDEX ix_products_variant_code_sku ON products USING btree(((data->>'variantCode')), product_sku);
该索引已经包含了你查询需要的两个字段,且索引本身按data->>'variantCode'排序,GROUP BY操作可以直接基于索引顺序完成,不需要回表查询,完全符合你走索引仅扫描的需求。
注意:要确保索引仅扫描生效,需要定期执行
VACUUM ANALYZE products;更新表的可见性映射,避免因为死元组未清理导致触发回表。
内容的提问来源于stack exchange,提问作者Romain Hautefeuille
相关产品推荐
相关产品推荐

