↑↓ 选择 ↵ 打开 ⌫ 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2
历史版本PostgreSQL 7.2 已于 2007 年 2 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本。

11.2. 规划器使用的统计信息 #

如上一节所见,查询规划器需要估计查询将检索多少行,才能对查询计划做出良好选择。本节简要介绍系统用于这些估计的统计信息。

统计信息的一部分是各个表和索引的条目总数,以及各个表和索引占用的磁盘块数。这些信息保存在pg_class的reltuples和relpages列中。可以使用类似下面的查询来查看:

regression=# select relname, relkind, reltuples, relpages from pg_class
regression-# where relname like 'tenk1%';

    relname    | relkind | reltuples | relpages
---------------+---------+-----------+----------
 tenk1         | r       |     10000 |      233
 tenk1_hundred | i       |     10000 |       30
 tenk1_unique1 | i       |     10000 |       30
 tenk1_unique2 | i       |     10000 |       30
(4 rows)

这里可以看到,tenk1包含 10000 行,它的索引也一样,但索引比表小得多(这并不意外)。

出于效率考虑,reltuples和relpages不会实时更新,因此它们通常只包含近似值(这对规划器的用途来说已经足够)。创建表时,它们被初始化为哑值(目前分别为 1000 和 10)。某些命令会更新它们,目前是VACUUM、ANALYZE和CREATE INDEX。独立的ANALYZE(即不作为VACUUM一部分执行的那种)由于不会读取表的每一行,生成的reltuples值是近似的。

大多数查询只会检索表中一部分行,因为它们通过 WHERE 子句限制了需要检查的行。因此,规划器需要估算 WHERE 子句的选择率,也就是满足 WHERE 条件中各个子句的行所占比例。完成这项任务所需的信息存储在pg_statistic系统目录中。pg_statistic中的条目由ANALYZE和VACUUM ANALYZE命令更新,而且即使刚更新完,也始终只是近似值。

手动检查统计信息时,与其直接查看pg_statistic,不如查看它的视图pg_stats。pg_stats旨在让统计信息更易读。此外,pg_stats所有用户都可以读取,而pg_statistic只有超级用户可以读取。(这可以防止没有相应权限的用户通过统计信息获知其他人表中的内容。pg_stats视图被限制为只显示当前用户有权读取的表的相关行。)例如,可以执行:

regression=# select attname, n_distinct, most_common_vals from pg_stats where tablename = 'road';

 attname | n_distinct |                                                                                                                                                                                  most_common_vals                                                                                                                                                                                   
---------+------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 name    |  -0.467008 | {"I- 580                        Ramp","I- 880                        Ramp","Sp Railroad                       ","I- 580                            ","I- 680                        Ramp","I- 80                         Ramp","14th                          St  ","5th                           St  ","Mission                       Blvd","I- 880                            "}
 thepath |         20 | {"[(-122.089,37.71),(-122.0886,37.711)]"}
(2 rows)
regression=#

从PostgreSQL 7.2 开始,pg_stats中存在下列列:

表 11.1. pg_stats 的列

名字 类型 描述
tablename name 包含该列的表的名字
attname name 此行描述的列
null_frac real 列中为 NULL 的项所占比例
avg_width integer 列的项的平均宽度(字节)
n_distinct real 如果大于零,是列中不同值的估计数量。如果小于零,是不同值数量除以行数的负值。(当 ANALYZE 认为不同值的数量可能随表的增长而增加时,使用取负形式;当列似乎有固定数量的可能值时,使用正形式。)例如,-1 表示一个唯一列,其不同值的数量与行数相同。
most_common_vals text[] 列中最常见值的列表。(如果看起来没有任何值比其他值更常见,则省略。)
most_common_freqs real[] 最常见值出现频率的列表,即每个值的出现次数除以总行数。
histogram_bounds text[] 把列的值划分成数量大致相等的组的值列表。most_common_vals(如果存在)会被排除在直方图计算之外。(如果列的数据类型没有<操作符,或者most_common_vals列表占了整个总体,则省略。)
correlation real 物理行顺序与列值逻辑顺序之间的统计相关性。取值范围从 -1 到 +1。当值接近 -1 或 +1 时,对该列的索引扫描会被估计为比接近零时更便宜,因为减少了磁盘的随机访问。(如果列的数据类型没有<操作符,则省略。)

most_common_vals和histogram_bounds数组中的最大项数可以使用ALTER TABLE SET STATISTICS命令按列设置。目前默认上限是 10 项。提高这一上限可能让规划器做出更准确的估计,尤其是对于数据分布不规则的列;代价则是pg_statistic占用更多空间,并且计算估计值所需时间也会略有增加。相反,对于数据分布较简单的列,较低的上限可能已经足够。

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。