周末在群里分享刚学到PG 18的两个优化特性:一个是DISTINCT及DISTINCT ON可以走索引而无需显式排序或利用增量排序;另外一个是Group By多个分组列的冗余消除功能。
早上又总结思考了一会,打算写一期PG数据库里的开心消消乐。

一、IS NOT NULL和IS NULL冗余消除

对于NOT NULL约束,17版本之前即便字段定义上有NOT NULL约束,查询还是会对数据逐行检查,甚至有时候走索引扫描时时还需要回表确认,这会显得不合理。而从17开始当表字段上有NOT NULL约束时:查询条件里有IS NOT NULL限制条件时,优化器能感知到并检测字段的NOT NULL约束,并删除冗余的IS NOT NULL限制条件。如果查询条件使用IS NULL,优化器能消除对NOT NULL字段的扫描,直接生成Result算子节点。
需要注意:只能是表字段直接定义的NOT NULL约束才有效,如果是间接定义,比如CHECK (column IS NOT NULL) 不会有效。
二、IS [NOT] UNKNOWN分区裁剪

从17版本开始,对布尔列使用IS [NOT] UNKNOWN条件查询时,能进行分区裁剪优化。
三、互斥条件冗余消除

当表字段的多个条件有冲突时,17版本之前的规划器还是会按第一个条件去生成plan,虽然后面并不会执行,但浪费了生成执行计划的时间。从17版本开始互斥条件会被直接消除。
四、Group By多列自适应重排

17版本针对Group By分组查询的列能自适应Order By子句的排序。这个功能还可通过GUC参数enable_group_by_reordering进行控制,默认启用。
总结:当使用多列Group By子句时,如果Group By子句的顺序与Order By子句或索引顺序一致,则可避免排序操作。
五、DISTINCT关键字排序优化

与17版本对Group By重排的特性相同,18对DISTINCT和DISTINCT ON也实现了类似的功能:可以避免不必要的重排或利用增量排序功能。

六、唯一索引消除冗余GROUP BY列

Group By多个分组列冗余消除条件:
- 有唯一索引列且非空时可消除
- 使用NULLS NOT DISTINCT定义的索引不需要NOT NULL约束也可消除





