ANALYZE — 收集有关数据库的统计信息
ANALYZE [ (option
[, ...] ) ] [table_and_columns
[, ...] ] whereoption
can be one of: VERBOSE [boolean
] SKIP_LOCKED [boolean
] BUFFER_USAGE_LIMITsize
andtable_and_columns
is:table_name
[ (column_name
[, ...] ) ]
ANALYZE
收集有关数据库中表内容的统计信息,并将结果存储在 pg_statistic
系统目录中。随后,查询计划器使用这些统计信息来帮助确定查询的最有效执行计划。
如果没有 table_and_columns
列表,ANALYZE
会处理当前数据库中当前用户有权分析的每个表和物化视图。如果带有列表,ANALYZE
只处理那些表。还可以为表提供列名列表,在这种情况下,只收集这些列的统计信息。
VERBOSE
启用显示进度消息。
SKIP_LOCKED
指定 ANALYZE
在开始处理关系时不等待任何冲突锁释放:如果不能立即锁定关系而不等待,则会跳过关系。请注意,即使使用此选项,ANALYZE
在打开关系的索引或从分区、表继承子项和某些类型的外部表获取样本行时,仍然可能阻塞。此外,虽然 ANALYZE
通常会处理指定的分区表的全部分区,但此选项会导致 ANALYZE
如果分区表存在冲突锁,则会跳过所有分区。
BUFFER_USAGE_LIMIT
指定 缓冲区访问策略 环形缓冲区大小,用于 ANALYZE
。此大小用于计算将被重新使用的共享缓冲区的数量,作为该策略的一部分。0
禁用使用 缓冲区访问策略
。如果未指定此选项,则 ANALYZE
使用来自 vacuum_buffer_usage_limit 的值。较高的设置可以使 ANALYZE
运行得更快,但设置过大可能会导致太多其他有用的页面从共享缓冲区中被驱逐。最小值为 128 kB
,最大值为 16 GB
。
boolean
指定是否应打开或关闭选定的选项。您可以编写 TRUE
、ON
或 1
来启用选项,并编写 FALSE
、OFF
或 0
来禁用它。boolean
值也可以省略,在这种情况下,默认为 TRUE
。
size
指定以千字节为单位的内存大小。大小也可以指定为包含数值大小和以下任一内存单位的字符串:B
(字节)、kB
(千字节)、MB
(兆字节)、GB
(吉字节)或 TB
(太字节)。
table_name
要分析的特定表的名称(可能是模式限定的)。如果省略,则分析当前数据库中的所有常规表、分区表和物化视图(但不分析外部表)。如果指定的表是分区表,则更新整个分区表的继承统计信息以及各个分区的统计信息。
column_name
要分析的特定列的名称。默认为所有列。
当指定 VERBOSE
时,ANALYZE
会向标准输出发送进度消息,以指示当前正在处理哪个表。还会打印有关表的各种统计信息。
要分析表,通常必须对表具有 MAINTAIN
权限。但是,数据库所有者可以分析其数据库中的所有表,共享目录除外。ANALYZE
会跳过调用用户无权分析的任何表。
外部表只有在显式选择时才会被分析。并非所有外部数据包装器都支持 ANALYZE
。如果表的包装器不支持 ANALYZE
,则命令会打印警告并执行任何操作。
在默认的 PostgreSQL 配置中,autovacuum 守护进程(参见 第 24.1.6 节)负责在首次加载数据时以及在整个正常运行过程中发生更改时自动分析表。如果禁用 autovacuum,则最好定期运行 ANALYZE
,或者在对表内容进行重大更改后立即运行。准确的统计信息将帮助计划器选择最合适的查询计划,从而提高查询处理速度。对于以读取为主的数据库,一个常见的策略是在一天中使用量低的时段运行 VACUUM
和 ANALYZE
一次。(如果存在大量更新活动,这将不够。)
当 ANALYZE
正在运行时,search_path 会暂时更改为 pg_catalog, pg_temp
。
ANALYZE
只需要对目标表进行读锁,因此它可以与表上的其他非 DDL 活动并行运行。
ANALYZE
收集的统计信息通常包括每列中一些最常见值的列表以及显示每列中近似数据分布的直方图。如果 ANALYZE
认为它们不重要(例如,在唯一键列中,没有常见值)或列数据类型不支持相应的运算符,则可以省略其中一个或两个。有关统计信息的更多信息,请参见 第 24 章。
对于大型表,ANALYZE
会对表内容进行随机抽样,而不是检查每一行。这使得即使是非常大的表也可以在很短的时间内进行分析。但是,请注意,统计信息只是近似的,并且每次运行 ANALYZE
时都会略有变化,即使实际表内容没有改变。这可能会导致计划器估计的成本在 EXPLAIN
中显示的小幅变化。在极少数情况下,这种不确定性会导致计划器在运行 ANALYZE
后更改查询计划的选择。为了避免这种情况,请增加由 ANALYZE
收集的统计信息量,如下所述。
分析范围可以通过调整 default_statistics_target 配置变量来控制,或者通过使用 ALTER TABLE ... ALTER COLUMN ... SET STATISTICS
在列级设置每列统计信息目标来控制。目标值设置最常见值列表中的最大条目数和直方图中的最大 bin 数。默认目标值为 100,但可以将其向上或向下调整,以权衡计划器估计的准确性与 ANALYZE
所用时间以及 pg_statistic
中所占空间的大小。特别是,将统计信息目标设置为零会禁用该列的统计信息收集。这对于从不作为查询的 WHERE
、GROUP BY
或 ORDER BY
子句的一部分使用的列可能很有用,因为计划器不会使用此类列的统计信息。
正在分析的列中最大的统计信息目标决定了为准备统计信息而采样的表行数。增加目标会导致 ANALYZE
所需时间和空间的成比例增加。
ANALYZE
估计的值之一是每列中出现的不同值的数目。因为只检查了行的一部分,所以即使使用最大的统计信息目标,这种估计有时也可能非常不准确。如果这种不准确导致了错误的查询计划,则可以通过手动确定更准确的值,然后使用 ALTER TABLE ... ALTER COLUMN ... SET (n_distinct = ...)
安装它。
如果正在分析的表具有继承子项,则 ANALYZE
会收集两组统计信息:一组仅针对父表中的行,另一组包括父表及其所有子项中的行。当规划处理整个继承树的查询时,需要第二组统计信息。在这种情况下,子表本身不会被单独分析。但是,autovacuum 守护进程只会在决定是否为该表触发自动分析时考虑对父表本身的插入或更新操作。如果很少向该表插入或更新数据,那么除非手动运行 ANALYZE
,否则继承统计信息将不会是最新的。
对于分区表,ANALYZE
通过从所有分区中抽样行来收集统计信息;此外,它会递归进入每个分区并更新其统计信息。每个叶子分区只分析一次,即使是多级分区也是如此。不会收集仅针对父表(不包含其分区中的数据)的统计信息,因为分区保证为空。
自动清理守护进程不会处理分区表,也不会处理继承父表,除非只有子表被修改。通常需要定期手动运行 `ANALYZE` 命令来保持表层次结构的统计信息更新。
如果任何子表或分区是其外部数据包装器不支持 `ANALYZE` 命令的外部表,则在收集继承统计信息时会忽略这些表。
如果要分析的表完全为空,`ANALYZE` 命令不会为该表记录新的统计信息。任何现有的统计信息将被保留。
每个运行 `ANALYZE` 命令的后端将在 `pg_stat_progress_analyze` 视图中报告其进度。有关详细信息,请参见 [第 27.4.1 节](progress-reporting.html#ANALYZE-PROGRESS-REPORTING)。
SQL 标准中没有 `ANALYZE` 语句。
在 PostgreSQL 11 版本之前,使用以下语法,并且仍然支持。
ANALYZE [ VERBOSE ] [ table_and_columns
[, ...] ]
如果您发现文档中的任何内容不正确,与您对特定功能的体验不符,或者需要进一步澄清,请使用 [此表格](/account/comments/new/17/sql-analyze.html/) 报告文档问题。