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
禁用 Buffer Access Strategy
的使用。如果未指定此选项,ANALYZE
将从 vacuum_buffer_usage_limit 中使用值。较高设置可以让 ANALYZE
运行得更快,但如果设置太大,则可能会导致其他太多有用的页从共享缓冲区中被驱逐。最小值为 128 kB
,最大值为 16 GB
。
布尔型
指定选定的选项应开启还是关闭。你可编写 TRUE
、ON
或 1
以启用此选项,并编写 FALSE
、OFF
或 0
以禁用它。也可以省略 布尔型
值,此时假定为 TRUE
。
大小
指定以千字节为单位的内存量。还可以以字符串的形式来指定大小,该字符串包含数字大小后跟任意下列内存单位:B
(字节)、kB
(千字节)、MB
(兆字节)、GB
(千兆字节)或 TB
(太字节)。
table_name
要分析的特定表的名称(可能经过 schema 限定)。如果省略,将分析当前数据库中的所有普通表、已分区表和物化视图(但不包括外键表)。如果指定的表为已分区表,既会更新整个已分区表的继承统计信息,也会更新各个分区的统计信息。
column_name
要分析的特定列的名称。默认为所有列。
当指定了 VERBOSE
时,ANALYZE
会发出进度消息来指出当前处理哪个表。还会打印关于表的多项统计信息。
通常,分析表时需要在表上拥有 MAINTAIN
权限。但数据库所有者允许分析其数据库中的所有表,共享目录除外。ANALYZE
将跳过调用用户没有分析权限的任何表。
只有在被明确选择后才会分析外键表。并非所有外部数据包装器都支持 ANALYZE
。如果表包装器不支持 ANALYZE
,该命令会打印一个警告并不会有任何操作。
在默认 PostgreSQL 配置中,自动清理守护进程(参见 第 24.1.6 节)在表第一次装载数据时,以及根据常规操作的变化会自动负责分析表。当禁用自动清理时,不妨定期运行 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
设置每列统计数据目标来控制分析范围。目标值设定在最常见值列表中的最大条目数和直方图中的最大分段数。默认目标值为 100,但可以向上或向下调整,既考虑到规划器估算的精度,又能兼顾 ANALYZE
的耗时以及 pg_statistic
中占用的空间。特别是,将统计目标设置为 0 会禁止收集该列的统计数据。对于从不作为查询 WHERE
、GROUP BY
或 ORDER BY
子句一部分的列,这样做可能很有用,因为规划器不会使用此类列的统计数据。
正在分析的列中最大的统计目标确定准备统计要进行抽样的表行数量。增加目标会导致执行 ANALYZE
所需的时间和空间成比例增加。
由 ANALYZE
估算的一个值是每一列中出现的不同值的数量。因为仅检查子行,所以这个估算有时可能会相当不准确,即使有最大的可能的统计目标。如果这个不准确会导致错误的查询计划,则更加准确的值可以手动确定,然后使用 ALTER TABLE ... ALTER COLUMN ... SET (n_distinct = ...)
安装。
如果正在分析的表有继承子,ANALYZE
将收集两组统计信息:一组仅针对父表中的行,另一组包括父表及其所有子的行。在规划处理继承树整体的查询时需要第二组统计信息。在这种情况下,子表本身不会单独进行分析。然而,在决定对该表触发自动分析时,自动清理守护进程将仅考虑对父表本身的插入或更新。如果很少插入或更新该表,如果不手动运行 ANALYZE
,继承统计信息不会是最新的。
对于分区表,ANALYZE
通过从所有分区中抽样行来收集统计信息;此外,它将递归进入每个分区并更新其统计信息。即使在多级分区的情况下,每个叶分区也仅分析一次。因为分区的保证是空的,所以仅针对父表(没有分区中的数据)不会收集任何统计信息。
自动清理守护进程不处理分区表,也不处理仅修改孩子的继承父级。通常,需要定期手动运行 ANALYZE
来更新表层次结构的统计信息。
如果任何子表或分区是非公开表,并且其外部数据包装程序不支持 ANALYZE
,则在收集继承统计信息时将忽略那些表。
如果正在分析的表是完全空的,ANALYZE
不会为该表记录新统计信息。将保留任何现有的统计信息。
运行 ANALYZE
的每个后端都将在 pg_stat_progress_analyze
视图中报告其进度。有关详细信息,请参见第 27.4.1 节。
SQL 标准中没有 ANALYZE
语句。
在 PostgreSQL 11 版本之前,使用以下语法,仍然支持
ANALYZE [ VERBOSE ] [ table_and_columns
[, ...] ]