ANALYZE — 收集数据库的统计信息
ANALYZE [ (option[, ...] ) ] [table_and_columns[, ...] ] whereoptioncan be one of: VERBOSE [boolean] SKIP_LOCKED [boolean] BUFFER_USAGE_LIMITsizeandtable_and_columnsis: [ ONLY ]table_name[ * ] [ (column_name[, ...] ) ]
ANALYZE 收集有关数据库中表内容的统计信息,并把结果存储在 pg_statistic 系统目录中。随后,查询规划器会利用这些统计信息来帮助确定查询最高效的执行计划。
如果没有 table_and_columns 列表,ANALYZE 会处理当前数据库中当前用户有权分析的每一个表和物化视图。如果有列表,ANALYZE 只处理那些表。还可以进一步为某个表给出一个列名的列表,在这种情况下只会收集这些列的统计信息。
VERBOSE 启用以 INFO 级别显示进度消息。
SKIP_LOCKED 指定 ANALYZE 在开始处理一个关系时不应等待任何冲突的锁被释放:如果一个关系不能在不等待的情况下立即被锁定,则跳过该关系。注意,即使使用了该选项,在打开关系的索引时,或者从分区、表的继承子表以及某些类型的外部表获取样本行时,ANALYZE 仍可能阻塞。此外,虽然 ANALYZE 通常会处理指定的分区表的所有分区,但如果该分区表上存在冲突的锁,该选项将导致 ANALYZE 跳过所有分区。
BUFFER_USAGE_LIMIT 指定 缓冲区访问策略供 ANALYZE 使用的环形缓冲区大小。该大小用于计算将作为此策略的一部分被重用的共享缓冲区数量。0 会禁用对Buffer Access Strategy的使用。当未指定该选项时,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 要分析的特定表的名称(可以用模式限定)。如果省略,则分析当前数据库中的所有普通表、分区表和物化视图(但不包括外部表)。如果在表名之前指定了 ONLY,则只分析该表。如果未指定 ONLY,则分析该表及其所有继承子表或分区(如果有)。也可以选择在表名之后指定 *,以显式指明要分析继承子表(或分区)。
column_name要分析的特定列的名称。默认为所有列。
当指定了 VERBOSE 时,ANALYZE 会发出进度消息来指示当前正在处理哪个表。还会打印关于这些表的各种统计信息。
要分析一个表,通常必须拥有该表上的 MAINTAIN 权限。不过,数据库所有者可以分析其数据库中的所有表(共享目录除外)。ANALYZE 会跳过调用用户没有权限分析的任何表。
只有在显式选择外部表时才会分析它们。并非所有外部数据包装器都支持 ANALYZE。如果表的外部数据包装器不支持 ANALYZE,该命令会打印一条警告并且不做任何事情。
在默认的 PostgreSQL 配置中,自动清理守护进程(参见 Section 24.1.6)负责在表第一次加载数据时以及随着表在常规操作中发生变化时自动分析表。当自动清理被禁用时,最好定期运行 ANALYZE,或者在对表的内容做出重大更改之后立即运行。准确的统计信息将帮助规划器选择最合适的查询计划,从而提高查询处理的速度。对于以读为主的数据库,一种常见的策略是在一天中低使用量的时段每天运行一次 VACUUM 和 ANALYZE。(如果有大量更新活动,这就不够了。)
在 ANALYZE 运行期间,search_path 会被临时改为 pg_catalog, pg_temp。
ANALYZE 只需要对目标表的读锁,因此它可以与该表上的其他非 DDL 活动并行运行。
ANALYZE 收集的统计信息通常包括每个列中一些最常见值的列表,以及一个显示每个列中大致数据分布的直方图。如果 ANALYZE 认为它们没有意义(例如,在唯一键列中,没有常见值),或者该列的数据类型不支持相应的操作符,那么其中一项或两项都可以省略。关于统计信息的更多信息见 Chapter 24。
对于大型表,ANALYZE 会抽取表内容的一个随机样本,而不是检查每一行。这使得即使是超大的表也能在很短的时间内完成分析。但请注意,这些统计信息只是近似的,每次运行 ANALYZE 时都会略有变化,即使实际的表内容没有变化。这可能会导致 EXPLAIN 显示的规划器估计代价发生小的变化。在少数情况下,这种不确定性会导致规划器在 ANALYZE 运行后改变其对查询计划的选择。为了避免这种情况,可以按照下文所述提高 ANALYZE 收集的统计信息量。
分析的范围可以通过调整 default_statistics_target 配置变量来控制,也可以逐列地通过 ALTER TABLE ... ALTER COLUMN ... SET STATISTICS 设置每列的统计目标来控制。目标值设定了最常见值列表中的最大条目数和直方图中的最大桶数。默认目标值为 100,但可以向上或向下调整,以在规划器估计的准确性与 ANALYZE 所需的时间以及 pg_statistic 中占用的空间量之间进行权衡。特别地,将统计目标设置为零会禁用对该列的统计信息收集。对于从未在查询的 WHERE、GROUP BY 或 ORDER BY 子句中使用的列,这样做可能有用,因为规划器用不到这些列上的统计信息。
被分析的列中最大的统计目标决定了为准备统计信息而采样的表行数量。提高目标会使 ANALYZE 所需的时间和空间成比例地增加。
ANALYZE 估计的值之一是每个列中出现的不同值的数量。由于只检查了行的一个子集,这个估计有时可能相当不准确,即使使用最大可能的统计目标也是如此。如果这种不准确导致了糟糕的查询计划,可以手动确定一个更准确的值,然后用 ALTER TABLE ... ALTER COLUMN ... SET (n_distinct = ...) 安装它。
如果被分析的表有继承子表,ANALYZE 会收集两组统计信息:一组仅针对父表的行,另一组则包括父表及其所有子表的行。当规划把继承树作为一个整体处理的查询时,需要第二组统计信息。不过,自动清理守护进程在决定是否为该表触发自动分析时,只考虑对父表本身的插入或更新。如果该表很少被插入或更新,除非手动运行 ANALYZE,否则继承统计信息将不会是最新的。默认情况下,ANALYZE 还会递归地收集并更新每个继承子表的统计信息。可以使用 ONLY 关键字来禁用这一行为。
对于分区表,ANALYZE 通过从所有分区采样行来收集统计信息。默认情况下,ANALYZE 还会递归地收集并更新每个分区的统计信息。可以使用 ONLY 关键字来禁用这一行为。
自动清理守护进程不会处理分区表,如果只有子表被修改,它也不会处理继承父表。通常需要定期运行一次手动的 ANALYZE,以保持表层次结构的统计信息是最新的。
如果任何子表或分区是其外部数据包装器不支持 ANALYZE 的外部表,那么在收集继承统计信息时会忽略这些表。
如果被分析的表完全为空,ANALYZE 将不会为该表记录新的统计信息。任何现有的统计信息都将被保留。
每个运行 ANALYZE 的后端都会在 pg_stat_progress_analyze 视图中报告其进度。详见 Section 27.4.1。
SQL 标准中没有 ANALYZE 语句。
以下语法在 PostgreSQL 11 版之前使用,目前仍受支持:
ANALYZE [ VERBOSE ] [ table_and_columns [, ...] ]