选择 打开 改范围 完整检索页
受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10
当前 PostgreSQL 版本不在支持生命周期内。
您可以参阅当前版本的对应页面,或其他在上面列出的活跃大版本。

ANALYZE

ANALYZE — 收集数据库的统计信息

Synopsis

ANALYZE [ VERBOSE ] [ table_name [ ( column_name [, ...] ) ] ]

描述

ANALYZE收集数据库中各表内容的统计信息,并将结果存储到pg_statistic 系统目录中。随后,查询规划器会使用这些统计信息来帮助确定查询的最高效执行计划。

如果不带参数,ANALYZE 会检查当前数据库中的每个表。带有参数时,ANALYZE 只检查该表。还可以提供列名列表,这时只会收集这些列的统计信息。

参数

VERBOSE

启用进度消息显示。

table_name

要分析的特定表的名称(可带模式限定)。如果省略,则分析当前数据库中的所有普通表、分区表和物化视图(但不包括外部表)。如果指定的表是分区表,则会同时更新整个分区表的继承统计信息和各个分区的统计信息。

column_name

要分析的特定列的名称。默认为所有列。

输出

指定VERBOSE时,ANALYZE会输出进度消息, 指示当前正在处理哪个表,同时还会打印这些表的各种统计信息。

注解

要分析一个表,通常调用者必须是该表的拥有者或超级用户。 不过,数据库拥有者可以分析其数据库中的所有表,但共享系统目录除外。 (对共享系统目录的这一限制意味着,真正意义上的全数据库 ANALYZE 只能由超级用户执行。) ANALYZE 会跳过调用用户无权分析的任何表。

只有在显式选中时才会分析外部表。并非所有外部数据包装器都支持ANALYZE。 如果该表的包装器不支持ANALYZE,命令会打印一条警告且不执行任何操作。

在默认的PostgreSQL配置中,自动清理守护进程 (见Section 24.1.6)会在表首次装载数据时,以及在常规运行过程中数据发生变化时, 自动分析这些表。当自动清理被禁用时,最好定期运行ANALYZE, 或者在对表内容做出重大更改之后立即运行。准确的统计信息有助于规划器选择最合适的查询计划, 从而提高查询处理速度。对于以读取为主的数据库,一个常见策略是在每天使用率较低的时段运行一次 VACUUMANALYZE。 (如果更新活动很频繁,这样做仍然不够。)

ANALYZE只需获取目标表上的读锁,因此可以与该表上的其他活动并行运行。

ANALYZE收集的统计信息通常包括每列中某些高频值的列表,以及显示每列大致数据分布的直方图。如果ANALYZE认为它们没有意义(例如,唯一键列中没有高频值),或者列的数据类型不支持相应的操作符,则可能省略其中一项或两项。更多统计信息见Chapter 24

对于大型表,ANALYZE会对表内容进行随机采样,而不是检查每一行。 这使得即使是很大的表,也能在较短时间内完成分析。不过要注意,这些统计信息只是近似值, 并且即使实际表内容没有变化,每次运行ANALYZE时统计信息也会略有变化。 这可能导致EXPLAIN中显示的规划器估算代价略有变化。 在少数情况下,这种非确定性会导致规划器在运行ANALYZE之后改用不同的查询计划。 要避免这种情况,可以按下文所述提高ANALYZE收集的统计信息量。

可以通过调整配置变量default_statistics_target来控制分析程度, 也可以针对单个列使用ALTER TABLE ... ALTER COLUMN ... SET STATISTICS设置每列的统计信息目标(参见ALTER TABLE)。目标值会设置高频值列表中的最大条目数, 以及直方图中的最大桶数。默认目标值是 100,但可以把它调高或调低,以在规划器估算精度、 ANALYZE耗费的时间以及pg_statistic占用的空间之间作出权衡。 特别地,将统计信息目标设置为零会禁用该列的统计信息收集。对于那些从不出现在查询 WHEREGROUP BYORDER BY子句中的列, 这样做可能很有用,因为规划器不会用到这些列的统计信息。

被分析列中最大的统计信息目标决定了为了生成统计信息而需要采样的表行数。 增加该目标会导致执行ANALYZE所需的时间和空间按比例增加。

ANALYZE估算的值之一是每一列中出现的非重复值数量。由于只检查了部分行, 即使使用可能的最大统计信息目标,这种估计有时也可能相当不精确。如果这种不精确导致查询计划不佳, 就可以手工确定一个更精确的值,然后用 ALTER TABLE ... ALTER COLUMN ... SET (n_distinct = ...) 把该值设置进去(参见ALTER TABLE)。

如果被分析的表有继承子表,ANALYZE会收集两组统计信息: 一组只针对父表中的行,另一组则同时包含父表及其所有子表中的行。规划处理整个继承树的查询时, 需要第二组统计信息。在这种情况下,不会分别分析子表本身。不过,自动清理守护进程在决定是否为该表触发自动分析时, 只会考虑对父表本身的插入或更新。如果该表很少被插入或更新,那么除非手工运行 ANALYZE,否则继承统计信息就不会保持最新。

对于分区表,ANALYZE会通过对所有分区中的行进行采样来收集统计信息;此外,它还会递归进入每个分区并更新其统计信息。即使有多级分区,每个叶子分区也只分析一次。不会仅为父表收集统计信息(不含分区数据),因为分区机制保证父表为空。

自动清理守护进程不会处理分区表;如果继承体系中只有子表被修改,它也不会处理继承父表。 因此,通常需要定期手工运行ANALYZE,以保持表层次结构的统计信息为最新状态。

如果某些子表或分区是外部表,而其外部数据包装器不支持ANALYZE, 那么在收集继承统计信息时会忽略这些表。

如果被分析的表完全为空,ANALYZE将不会为该表记 录新的统计信息。任何现有统计信息都会被保留。

兼容性

SQL 标准中没有ANALYZE语句。