NULL VALUES
虽然理论学家对此不以为然,但 NULL 值在关系型数据库中仍然扮演着重要角色:它提供了一种方便的方式来表示某个值要么未知,要么不存在。
然而,特殊的值需要特殊处理。除了理论上的不一致性之外,还有许多实际问题需要考虑。常规的布尔逻辑被三值逻辑取代,因此 NOT IN 的行为可能出乎意料。对于 NULL 值应该被视为大于还是小于普通值也不明确(因此存在用于排序的 NULLS FIRST 和 NULLS LAST 子句)。是否需要在聚合函数中考虑 NULL 值也并不十分明显。严格来说,NULL 根本不是一个值,因此优化器在处理它们时需要额外的信息。
除了在表级收集的最基本的统计信息之外,分析器还会为表的每一列收集统计信息。这些数据存储在系统目录的 pg_statistic 表中,但你也可以通过 pg_stats 视图访问,这个视图以更方便的格式提供这些信息。
列级统计信息中包括 NULL 值的比例;在分析过程中计算,并以 null_frac 属性表示。
例如,当我们查询尚未起飞的航班时,可以依赖它们的起飞时间未定义(NULL)这一事实:
1 | => EXPLAIN SELECT * FROM flights WHERE actual_departure IS NULL; |
为了估算结果,优化器将表的总行数乘以 NULL 值的比例:
1 | => SELECT round(reltuples * s.null_frac) AS rows FROM pg_class |
以下是实际的行数:
1 | SELECT count(*) FROM flights WHERE actual_departure IS NULL; |