ANALYZE
描述
ANALYZE收集一个数据库中的表的内容的统计信息,并且将结果存储在pg_statistic系统目录中。接下来,查询规划器会使用这些统计信息来帮助确定查询最有效的执行计划。
如果不带参数,ANALYZE会检查当前数据库中的所有表。如果带有一个参数,ANALYZE只会检查那个表。可以进一步给出一个列名的列表,该情况下只会收集这些列的统计信息。
参数
- VERBOSE
-
允许显示进度消息。
- table_name
-
要分析的一个指定表的名称(可以是模式限定的)。如果省略,当前数据库中所有常规表(非外部表)都会被分析。
- column_name
-
要分析的一个指定列的名称。默认是所有列。
注解
只有被显式选中时才会分析外部表。并非所有外部数据包装器都支持ANALYZE。如果表的包装器不支持ANALYZE,该命令会打印一个警告并且什么也不做。
在默认的PostgreSQL配置中,自动清理守护进程(见第 24.1.6 节)会在表第一次载入数据或者用常规操作改变时负责表的自动分析。当启用自动清理时,定期运行ANALYZE是个好主意,或者可以在表内容做了大的修改后运行ANALYZE。准确的统计信息将帮助规划器选择最合适的查询计划,从而提升查询处理的速度。主读数据库的一般策略是在一天中使用量最低时运行一次VACUUM和ANALYZE(如果有大量的更新动作则是不够的)。
ANALYZE只要求目标表上的一个读锁,因此它可以和表上的其他动作并行。
ANALYZE收集的统计信息通畅包括每列中最常见值的列表以及展示每列中近似数据分布的一个直方图。如果ANALYZE认为这些东西无趣(例如在一个唯一键列中,没有共同值)或者该列的数据类型不支持合适的操作符,以上工作都会被省略。在第 24 章中有与统计信息相关的更多信息。
对于大型的表,ANALYZE会对表内容做随机采样而不是检查每一行。这允许在很少的时间内完成对大型表的分析。不过要注意,这些统计信息只是近似值,并且即使实际表内容没有改变,每次运行ANALYZE时统计信息都会有微小地改变。这可能会导致EXPLAIN显示的规划器估算代价有小的改变。在很少的情况下,这会非决定性地导致规划器的查询计划选择在ANALYZE运行后改变。为了避免这种情况,可以按照下文所述提高ANALYZE所收集的统计信息量。
通过调整default_statistics_target配置变量可以控制分析量,对每个列可以用ALTER TABLE ... ALTER COLUMN ... SET STATISTICS设置每列的统计信息目标(见ALTER TABLE)。目标值会设置最常用值列表中的最大项数以及直方图中的最大容器数。默认目标值是 100,可以把它调大或者调小在规划器估计值精度和ANALYZE花费的时间以及pg_statistic所占空间之间做出平衡。特别地,将统计信息目标设置为零会禁用该列的统计信息收集。在查询的WHERE、GROUP BY或者ORDER BY子句中从不出现的列上这样做会有所帮助,因为规划器用不上这些列上的统计信息。
被分析的列中最大的统计信息目标决定了为准备统计信息要采样的表行数。增加该目标会导致做ANALYZE所需的时间和空间成比例增加。
ANALYZE所估算的值之一是出现在每个列中的可区分值。因为只会检查行的一个子集,即便使用最大的统计信息目标,这种估计有时也可能很不精确。如果这种不精确导致不好的查询计划,可以手工确定一个更精确的值并且用ALTER TABLE ... ALTER COLUMN ... SET (n_distinct = ...)设置该值(见ALTER TABLE)。
如果被分析的表有一个或者更多子女,ANALYZE将会收集两次统计信息:一次只对父表的行收集,第二次则在父表及其所有子女表的行上收集。在规划需要遍历整个继承树的查询时需要第二个统计信息集。不过,在决定是否触发表上的自动分析时,自动清理后台进程将只考虑父表本身上的插入和更新。如果该表很少被插入或者更新,只有手工运行ANALYZE时才会把继承统计信息更新到最新。
如果任何子表是外部表并且其外部数据包装器不支持ANALYZE,在收集继承统计信息时会忽略那些子表。
如果被分析的表不完全为空,ANALYZE将不会为该表记录新统计信息。任何现有统计信息将会被保留。