pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
如上一节所见,查询规划器需要估计查询将检索多少行,才能对查询计划做出良好选择。本节简要介绍系统用于这些估计的统计信息。
统计信息的一部分是各个表和索引的条目总数,以及各个表和索引占用的磁盘块数。这些信息保存在表pg_class的reltuples和relpages列中。可以使用类似下面的查询来查看:
SELECT relname, relkind, reltuples, relpages
FROM pg_class
WHERE relname LIKE 'tenk1%';
relname | relkind | reltuples | relpages
----------------------+---------+-----------+----------
tenk1 | r | 10000 | 358
tenk1_hundred | i | 10000 | 30
tenk1_thous_tenthous | i | 10000 | 30
tenk1_unique1 | i | 10000 | 30
tenk1_unique2 | i | 10000 | 30
(5 rows)
这里可以看到,tenk1包含 10000 行,它的索引也一样,但索引比表小得多(这并不意外)。
出于效率考虑,reltuples和relpages不会实时更新,因此它们通常包含有些过时的值。它们会在VACUUM、ANALYZE以及少数 DDL 命令(如CREATE INDEX)执行时被更新。独立执行的ANALYZE(即不属于VACUUM的那种)由于不会读取表中的每一行,生成的是reltuples的近似值。无论如何,规划器都会将它在pg_class中找到的值按当前物理表大小进行缩放,从而得到更接近实际情况的近似值。
大多数查询只会检索表中一部分行,因为它们通过WHERE子句限制了需要检查的行。因此,规划器需要估算WHERE子句的选择度,也就是满足WHERE子句中各个条件的行所占比例。完成这项任务所需的信息存储在pg_statistic系统目录中。pg_statistic中的条目由ANALYZE和VACUUM ANALYZE命令更新,而且即使刚更新完,也始终只是近似值。
手动检查统计信息时,与其直接查看pg_statistic,不如查看它的视图pg_stats。pg_stats旨在让统计信息更易读。此外,pg_stats所有用户都可以读取,而pg_statistic只有超级用户可以读取。(这可以防止没有相应权限的用户通过统计信息获知其他用户表中的内容。pg_stats视图被限制为只显示当前用户有权读取的表的相关行。)例如,可以执行:
SELECT attname, inherited, n_distinct,
array_to_string(most_common_vals, E'\n') as most_common_vals
FROM pg_stats
WHERE tablename = 'road';
attname | inherited | n_distinct | most_common_vals
---------+-----------+------------+------------------------------------
name | f | -0.363388 | I- 580 Ramp+
| | | I- 880 Ramp+
| | | Sp Railroad +
| | | I- 580 +
| | | I- 680 Ramp
name | t | -0.284859 | I- 880 Ramp+
| | | I- 580 Ramp+
| | | I- 680 Ramp+
| | | I- 580 +
| | | State Hwy 13 Ramp
(2 rows)
注意,同一列显示了两行,其中一行对应从road表开始的整个继承层次结构(inherited=t),另一行只包含road表本身(inherited=f)。
ANALYZE在pg_statistic中存储的信息量,特别是每列most_common_vals中的最大项数和histogram_bounds数组的大小,可以使用ALTER TABLE SET STATISTICS命令按列设置,也可以通过设置配置变量default_statistics_target进行全局设置。目前默认上限是 100 项。提高这一上限可能让规划器做出更准确的估计,尤其是对于数据分布不规则的列;代价则是pg_statistic占用更多空间,并且计算估计值所需时间也会略有增加。相反,对于数据分布较简单的列,较低的上限可能已经足够。
更多规划器对统计信息的使用可参阅第 57 章。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。