ANALYZE收集数据库中表内容的统计信息,然后把结果保存在系统表pg_statistic里。 随后,查询规划器就可以使用这些统计帮助判断查询的最佳规划。
使用本命令时如果不带任何参数,ANALYZE将检查当前数据库里的所有表。 如果有参数,ANALYZE只检查那个指定的表。 你还可以指定一些字段的名字,在这种情况下,将只收集那些字段的统计信息。
显示处理过程的信息。
要分析的指定表(可以用模式名修饰)的名字。缺省是当前数据库里所有表(不包含外部数据表)。
要分析的指定字段的名字。缺省是所有字段。
只有在明确指定了外部数据表时,这些表才会被分析处理。也不是所有的外部数据封装器都支持ANALYZE。 如果表的封装器不支持ANALYZE,在执行此命令时会显示一个警告信息,系统不会做任何处理。
在默认的PostgreSQL配置中,autovacuum守护进程(参见第 23.1.6 节)负责在初次加载数据时自动分析表。 因为它们会改变整个常规操作。 当autovacuum关闭时,周期性地运行ANALYZE,或者在对表的大部分内容做了更改之后马上运行它是个好习惯。 准确的统计信息将帮助规划器选择最合适的查询规划,并因此改善查询处理的速度。 对以读取为主要负载的数据库,一种比较经常采用的策略是每天在低负荷的时候运行一次VACUUM和ANALYZE 。
ANALYZE只需要在目标表上有一个读取锁,因此它可以和表上的其它活动并发地运行。
ANALYZE收集的统计信息通常包括每个字段最常用数值的列表以及显示每个字段里数据近似分布的柱状图。 如果ANALYZE认为它们都没有什么用(比如在一个拥有唯一约束的字段上没有公共的数值)或者是该字段数据类型不支持相关的操作符,那么它们都可以忽略。 在第 23 章中有关于统计的更多信息。
对于大表,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将会收集统计两次: 一次仅仅在父表的行上,第二次是在父表及其所有子表的行上。 第二次收集的统计数据在查询规划器遍历整个继承树结构时会用到。 不过,autovacuum守护进程在决定触发一个对一个表的自动分析时,会仅仅考虑在父表上进行插入或者更新。 如果那个表几乎不插入或者更新,继承的统计数据将不再更新,除非您手动运行ANALYZE。
如果拟分析的表成了一个空表,则ANALYZE不会记录该表的统计信息。而原来已有有统计信息则会保留。