关于Greenplum数据库中的数据库统计信息
关于Greenplum数据库中的数据库统计信息
Greenplum数据库中通过ANALYZE命令收集的统计信息的概述。
统计信息是描述数据库中数据的元数据。 查询优化器需要最新的统计信息以便为查询选择最好的执行计划。 例如,如果一个查询连接两个表并且其中的一个必须被广播到所有的Segment,优化器可以选择两个表中较小的那一个来最小化网络流量。
- 用户可以直接运行ANALYZE命令。
- 用户可以在数据库外部从命令行运行analyzedb管理工具。
- 当在没有统计信息的表上执行DML操作或者一个DML操作修改的行数超过指定阈值时,会触发一次自动的分析操作。
计算统计信息需要消耗时间和资源,因此Greenplum数据库通过在大型表的采样上计算统计信息来得到估计值。 在大部分情况下,默认的设置提供了足以为查询生成正确执行计划的信息。 如果产生的统计信息没有产生最优的查询执行计划,管理员可以调节配置参数通过提高样本尺寸或者系统目录中保存的统计信息粒度来产生更准确的统计信息。 产生更准确的统计信息需要CPU和存储代价并且不一定能产生更好的计划,因此重点是查看解释计划并且测试查询性能来确保额外的统计信息代价能导致更好的查询性能。
系统统计信息
表尺寸
查询规划器想要最小化执行查询所需的磁盘I/O和网络流量,它会使用必须被处理的行数以及查询必须访问的磁盘页面数的估计值。 用于生成这些估计值的数据是pg_class系统表列reltuples和relpages,它们分别包含上一次VACUUM或ANALYZE命令运行时的行数和页面数。 随着行被增加或删除,这些数字变得越来越不准确。 不过,总是可以从操作系统拿到准确的磁盘页面计数,因此只要reltuples与relpages的比例不发生显著变化,优化器就能够产生对选择正确的查询执行计划足够准确的行数估计。
当reltuples列与SELECT COUNT(*)返回的行计数显著不同时,应该执行一次分析来更新统计信息。当一个REINDEX命令完成了重建一个索引时,relpages和reltuples列被设置为零。应该在基表上运行ANALYZE命令以更新这些列。
pg_statistic系统表和pg_stats视图
- starelid
- 该列所属的表或索引的对象ID。
- staattnum
- 所描述列的编号,从1开始。
- stainherit
- 如果值是true,统计信息不仅包括指定的relation,还包括继承的子列。
- stanullfrac
- 列中为空的项的分数值。
- stawidth
- 非空项的平均存储宽度,单位是字节。
- stadistinct
- 一个正数,它是列中可区分值的数量估计。这个数字预计并不会随着行数变化。 一个负值是可区分值数量除以行数,也就是该列中有可区分值的行的比例取负值。 当可区分值数量随行数增加时使用这种形式。例如,一个唯一列的n_distinct值为-1.0。 平均宽度超过1024的列被认为是唯一的。
- stakindN
- 一个代码数字,它表示存储在pg_statistic行第N个槽中的统计信息类型。
- staopN
- 用来得到第N个槽中统计信息的操作符。例如,一个直方图槽会显示 < 操作符,它定义数据的排序顺序。
- stanumbersN
- float4数组,包含第N个槽的合适类型的数字统计信息,如果槽类型不涉及数字值则为NULL。
- stavaluesN
- 第N个槽的合适类型的列数据值,如果该槽类型不存储任何数据值则为NULL。 每一个数组的元素值实际是指定列的数据类型,因此没有办法比使用anyarray更具体地定义这些列的类型。
为一个列收集的统计信息随着不同数据类型变化,因此pg_statistic表中存储适合于四个槽中数据类型的统计信息,每个槽由四个列组成。 例如,第一个槽通常包含一列的最常见值,它由列stakind1、staop1、stanumbers1和stavalues1组成。
stakind代码 | 描述 |
---|---|
1 |
最常见值(MCV)槽
|
2 |
直方图槽 – 描述标量数据的分布。
如果也提供了一个最常见值的槽,那么该直方图描述的是将MCV数组中列出的值移除后的数据分布(在技术上的说法是一个压缩直方图)。 这允许更精确地表示一个有一些非常常见值的列的分布。 在一个只有一些可区分值的列中,有可能MCV列表就描述了整个数据群体,在这种情况下直方图缩小为空并且应该被省略。 |
3 | 相关关系槽 – 描述表元组物理顺序和列数据值顺序之间的相关关系。
|
4 | 最常见的元素插槽 - 类似于最常见值(MCV)插槽,除了它存储列值的最常见非空元素。
当列数据类型是数组或具有可识别元素的其他类型(例如,tsvector)时,这非常有用。
频率测量为元素值出现的非空行的分数,而不是所有行的频率。 此外,值将按元素类型的默认顺序排序(以支持特定值的二分查找)。 由于这会将最小和最大频率放在不稳定点上,因此有两个额外的stanumbers成员可以保存最小和最大频率的副本。 可选地,可以存在保持空元素的频率的第三额外成员(频率以相同的术语表示:包含至少一个空元素的非空行的分数)。 如果省略此成员,则假定该列不包含NULL元素。
Note: 注意:对于tsvector列,stavalues元素的类型为text,即使它们在tsvector中的表示不完全是文本。
|
5 | 不同的元素计数直方图槽 - 描述了数组类型列的每一行中存在的不同元素值的数量的分布。 仅考虑非空行,并且仅考虑非空元素。
|
99 | 超级日志槽 - 对于分区表的子叶分区,存储为采样数据创建的超级日志计数器。 hyperloglog_counter数据结构转换为bytea并存储在pg_statistic目录表的stavalues5插槽中。 |
- schemaname
- 包含该表的方案名称。
- tablename
- 该表的名称。
- attname
- 这行所描述的列名。
- inherited
- 如果为true,统计信息包含继承的子列。
- null_frac
- 为空的列项所占的比例。
- avg_width
- 该列中项的平均存储宽度(以字节为单位),计算方法是avg(pg_column_size(column_name))。
- n_distinct
- 一个正数是该列中可区分值的数量估计。这个数字预计并不会随着行数变化。 一个负值是可区分值数量除以行数,也就是该列中有可区分值的行的比例取负值。 当可区分值数量随行数增加时使用这种形式。例如,一个唯一列的n_distinct值为-1.0。 平均宽度超过1024的列被认为是唯一的。
- most_common_vals
- 包含该列中最常见值的数组,如果没有值看起来更常见则为空。 如果n_distinct列为-1,则most_common_vals为空。 这个数组的长度小于实际的可区分列值的数量或者default_statistics_target配置参数的值。 对一个列可以使用ALTER TABLE table SET COLUMN column SET STATISTICS N覆盖值的数量。
- most_common_freqs
- 包含most_common_vals数组中值的频率。它是一个值的出现次数除以总行数。 这个数组和most_common_vals数组的长度相等。如果most_common_vals为空,则它也为空。
- histogram_bounds
- 一个值数组,它把列值划分成大约相同尺寸的分组。只有对该列有一个max()聚集函数时才能定义直方图。 直方图中分组的数量等于most_common_vals数组的尺寸。
- correlation
- Greenplum数据库不计算相关关系统计信息。
- most_common_elems
- 包含最常见元素值的数组。
- most_common_elem_freqs
- 包含公共元素频率的数组。
- elem_count_histogram
- 一个数组,描述数组类型列的每一行中存在的不同元素值的数量的分布。
SELECT * from gp_toolkit.gp_stats_missing;
采样
在为大型表计算统计信息时,Greenplum数据库通过采样基表来创建一个较小的表。如果表被分过区,会从所有的分区取得抽样。
更新统计信息
运行不带参数的ANALYZE会为数据库中的所有表更新统计信息。 这可能会耗费非常长的时间,因此更好的方式是在数据被改变后有选择地分析表。 用户还可以分析一个表中的列子集,例如连接中、WHERE子句、SORT子句、GROUP BY子句或者HAVING子句中用到的列。
如果采样中包含空页面,分析一个严重膨胀的表可能生成不好的统计信息,因此最好的做法是在分析一个膨胀了的表之前先清理它。
运行ANALYZE命令的详情请见Greenplum数据库参考指南中的SQL命令参考。
运行analyzedb命令的细节请参考Greenplum数据库管理工具参考。
分析分区表
当ANALYZE命令被运行在一个分区表上时,它会逐个分析每一个叶子层子分区。 用户可以只在新的或者更改过的分区表上运行ANALYZE以避免分析没有变化过的分区。
analyzedb命令行工具会自动跳过未更改的分区。它还会运行并发会话,这样它可以并发地分析几个分区。 默认它会运行五个会话,但会话的数量可以用-p命令行选项设置为1至10。 analyzedb每次运行时,它会在Master数据目录中的db_analyze目录下为追加优化表和分区保存状态信息。 下一次它运行时,analyzedb会把每个表的当前状态与其保存状态相比较,并且跳过没有更改的表或分区。堆表总是会被分析。
如果GPORCA被启用(默认),用户还需要运行ANALYZE ROOTPARTITION来刷新根分区的统计信息。 GPORCA要求在分区表根层的统计信息。传统优化器不使用这些统计信息。
分析分区表的时间类似于分析具有相同数据的非分区表的时间,因为ANALYZE ROOTPARTITION不收集叶分区上的统计信息(仅对数据进行采样)。 analyzedb工具默认会更新根分区统计信息
Greenplum数据库服务器配置参数optimizer_analyze_root_partition会影响何时在分区表的根分区上收集统计信息。 如果参数为on(缺省值),则在运行ANALYZE时,不需要ROOTPARTITION关键字来收集根分区的统计信息。 在根分区上运行ANALYZE时,或者在分区表的子叶子分区上运行ANALYZE并且其他子叶子分区具有统计信息时,将收集根分区统计信息。 如果参数关闭,则必须运行ANALYZE ROOTPARTITION以收集根分区统计信息。如果您不打算使用GPORCA对分区表执行查询(将服务器配置参数optimizer设置为关闭), 则还可以将服务器配置参数optimizer_analyze_root_partition设置为off,以限制ANALYZE更新根分区统计信息的时间。
配置统计信息
有几个选项可以配置Greenplum数据库的统计信息收集。
统计信息目标
统计信息目标是一个列的most_common_vals、most_common_freqs以及histogram_bounds数组的尺寸。 默认情况下,目标是25。默认目标可以通过设置一个服务器配置参数来更改,对任意列可以使用ALTER TABLE命令设置目标。 较大的值会增加执行ANALYZE所需的时间,但是可能会增加传统查询优化器(规划器)估计值的质量。
gpconfig -c default_statistics_target -v 150
可以使用ALTER TABLE命令设置各列的统计信息目标。 例如,某些查询可以通过增加某些列的目标来改进,尤其是具有不规则分布的列。 对于从不参与查询优化的列,您可以将目标设置为零。 当目标是0,ANALYZE会忽略该列。 例如,以下ALTER TABLE命令将emp表中notes列的统计信息目标设置为零:
ALTER TABLE emp ALTER COLUMN notes SET STATISTICS 0;
统计信息目标可以被设置为0到1000,或者把它设置为-1以回到使用系统的默认统计信息目标。
在父分区表上设置统计信息目标会影响子分区。 如果在父表上把某些列的统计信息目标设置为0,对所有子分区也会把相同列的统计信息目标设置为0。 不过,如果用户后来增加或者交换了另一个子分区,新的子分区将会使用默认统计信息目标或者之前的统计信息目标(在交换的情况下)。 因此,如果用户增加或者交换子分区,应该在新的子表上设置统计信息目标。
自动统计收集
Greenplum数据库可以被设置为在没有统计信息或者在执行特定操作后发生显著改变的表上自动地运行ANALYZE。 对于分区表,自动统计收集只在操作直接运行在叶子表上时才被触发,然后也只会分析这个叶子表。
- none 禁用自动统计收集。
- 当任意一个CREATE TABLE AS SELECT、INSERT或者COPY命令在没有现存统计信息的表上执行时,on_no_stats模式会为该表触发一次分析操作。
- 当任意一个CREATE TABLE AS SELECT、UPDATE、DELETE、INSERT或者COPY命令在表上执行并且被影响的行数超过gp_autostats_on_change_threshold配置参数所定义的阈值时, on_change模式会为该表触发一次分析操作
- gp_autostats_mode配置参数控制函数外自动统计收集的行为并且默认被设置为on_no_stats。
- gp_autostats_mode_in_functions参数控制表操作在一个过程语言函数内执行时的行为并且默认被设置为none。
通过on_change模式,只有受影响的行数超过gp_autostats_on_change_threshold配置参数所定义的阈值时才会触发ANALYZE。 这个参数的默认值是一个非常高的值2147483647,它实际上禁用了自动统计收集。 用户必须将该阈值设置得较低来启用它。on_change模式可能会触发大型的、预期之外的分析操作,它们可能会中断系统,因此不推荐在全局范围内设置它。 在一个会话中它可能会有用,例如在一次装载后自动分析一个表。
gpconfigure -c gp_autostats_mode -v none
gpconfigure -c gp_autostats_mode_in_functions -v on_no_stats
如果想要记录自动统计收集操作,可将log_autostats系统配置参数设置为on。