首页
学习
活动
专区
工具
TVP
发布

《Greenplum数据库文档》系列之Greenplum数据库概念

为了方便大家更好的了解和使用Greenplum数据库,我们将陆续推送Greenplum数据库文档的相关内容。该文档节选自由武汉大学彭煜玮,邰凌翔,韩珂,兰海翻译的《Greenplum数据库中文文档》。

这一节给出了Greenplum数据库组件和特性的概述,例如高可用性、并行数据装载特性以及管理工具。

关于Greenplum的架构

Greenplum数据库是一种大规模并行处理(MPP)数据库服务器,其架构特别针对管理大规模分析型数据仓库以及商业智能工作负载而设计。

MPP(也被称为shared nothing架构)指有两个或者更多个处理器协同执行一个操作的系统,每一个处理器都有其自己的内存、操作系统和磁盘。Greenplum使用这种高性能系统架构来分布数T字节数据仓库的负载并且能够使用系统的所有资源并行处理一个查询。

Greenplum数据库是基于PostgreSQL开源技术的。它本质上是多个PostgreSQL面向磁盘的数据库实例一起工作形成的一个紧密结合的数据库管理系统(DBMS)。它基于PostgreSQL 8.3.23开发,其SQL支持、特性、配置选项和最终用户功能在大部分情况下和PostgreSQL非常相似。与Greenplum数据库交互的数据库用户会感觉在使用一个常规的PostgreSQL DBMS。

Greenplum数据库可以使用追加优化(append-optimized,AO)的存储个事来批量装载和读取数据,并且能提供HEAP表上的性能优势。追加优化的存储为数据保护、压缩和行/列方向提供了校验和。行式或者列式追加优化的表都可以被压缩。

Greenplum数据库和PostgreSQL的主要区别在于:

·在基于Postgres查询规划器的常规查询规划器之外,可以利用GPORCA进行查询规划。

·Greenplum数据库可以使用追加优化的存储。

·Greenplum数据库可以选用列式存储,数据在逻辑上还是组织成一个表,但其中的行和列在物理上是存储在一种面向列的格式中,而不是存储成行。列式存储只能和追加优化表一起使用。列式存储是可压缩的。当用户只需要返回感兴趣的列时,列式存储可以提供更好的性能。所有的压缩算法都可以用在行式或者列式存储的表上,但是行程编码(RLE)压缩只能用于列式存储的表。Greenplum数据库在所有使用列式存储的追加优化表上都提供了压缩。

为了支持Greenplum数据库的并行结构,PostgreSQL的内部已经被修改或者增补。例如,系统目录、优化器、查询执行器以及事务管理器组件都已经被修改或者增强,以便能够在所有的并行PostgreSQL数据库实例之上同时执行查询。Greenplum的Interconnect(网络层)允许在不同的PostgreSQL实例之间通讯,让系统表现为一个逻辑数据库。

Greenplum数据库也可以使用声明式分区和子分区来隐式地生成分区约束。

Greenplum数据库也包括为针对商业智能(BI)负载优化PostgreSQL而设计的特性。例如,Greenplum增加了并行数据装载(外部表)、资源管理、查询优化以及存储增强,这些在PostgreSQL中都是无法找到的。很多Greenplum开发的特性和优化都在PostgreSQL社区中找到了一席之地。例如,表分区最初是由Greenplum开发的一个特性,现在已经出现在了标准的PostgreSQL中。

Greenplum数据库的查询使用一种火山式查询引擎模型,其中的执行引擎拿到一个执行计划并且用它产生一棵物理操作符树,然后通过物理操作符计算表,最后返回结果作为查询响应。

Greenplum数据库通过将数据和处理负载分布在多个服务器或者主机上来存储和处理大量的数据。Greenplum数据库是一个由基于PostgreSQL 8.3的数据库组成的阵列,阵列中的数据库工作在一起呈现了一个单一数据库的景象。Master是Greenplum数据库系统的入口。客户端会连接到这个数据库实例并且提交SQL语句。Master会协调与系统中其他称为Segment的数据库实例一起工作,Segment负责存储和处理数据。

图 1. 高层的Greenplum数据库架构

关于管理和监控工具

Greenplum数据库提供了标准的命令行工具来执行通常的监控和管理任务。

Greenplum的命令行工具位于 $GPHOME/bin目录中并且在Master主机上执行。Greenplum为下列管理任务提供了实用工具:

·在一个阵列上安装Greenplum数据库

·初始化一个Greenplum数据库系统

·开始和停止Greenplum数据库

·增加或者移除一个主机

·扩展阵列并且在新的Segment上重新分布表

·恢复失效的Segment实例

·管理失效Master实例的故障切换和恢复

·备份和恢复一个数据库(并行)

·并行装载数据

·在Greenplum数据库之间转移数据

·系统状态报告

Greenplum数据库包括一个gpperfmon_install管理工具,它会创建gpperfmon数据库并且启用数据收集代理。用户可以查询gpperfmon数据库来查看查询和系统指标。

关于Greenplum数据库中的并发控制

Greenplum数据库使用了PostgreSQL的多版本并发控制(MVCC)模型来管理对于堆表的并发事务。

数据库管理系统中的并发控制允许在确保数据库的完整性的前提下,并发查询能够完成并且得到正确的结果。传统的数据库使用两阶段锁协议来阻止一个事务修改已经被另一个并发事务读取的数据并且阻止任何并发事务读取或者写入另一个事务已经更新的数据。协调事务所需的锁增加了数据库中的竞争,降低了总体事务吞吐量。

Greenplum数据库使用PostgreSQL的多版本并发控制(MVCC)模型来管理堆表的并发。通过MVCC,每一个查询都在它开始时的一个数据库快照上操作。在执行时,一个查询不能看到其他并发事务所作出的更改。这确保了一个查询看到的是数据库的一个一致的视图。读取行的查询不会被写入行的事务所阻塞。反过来,写入行的查询也不会被读取行的事务所阻塞。这使得Greenplum可以达到比使用锁来协调读写事务的传统数据库系统更高的并发度。

注意:追加优化表使用一种不同于MVCC的并发控制模型管理。它们是为了“一次写,多次读”的应用而设计,这些应用从不或者很少会进行行级更新。

快照

MVCC模型依赖于系统能够管理数据行的多个版本的能力。一个查询其实是在该查询开始时的数据库快照上操作。快照就是在一个语句或者事务开始时可见的行的集合。快照保证查询在其执行期间看到的是数据库的一个一致且合法的视图。

每一个事务都会被分配一个唯一的事务ID(XID),它是一个增量式的32位值。当一个新事务开始时,它被分配下一个XID。没有被包裹在一个事务中的一个SQL语句会被当做一个单语句事务,即会给它隐式地加上BEGIN和COMMIT。这和一些数据库系统中的自动提交概念类似。

注意:Greenplum数据库只为涉及DDL或者DML操作的事务分配XID值,它们通常是唯一需要XID的事务。

当一个事务插入一行时,其XID会被保存在该行的 xmin系统列中。当一个事务删除一行时,其XID会被保存在xmax系统列中。更新一行被视为一次删除加上一次插入,因此XID会被保存在当前行的xmax中以及新插入行的xmin中。xmin和 xmax列再加上事务完成状态就指定了一个事务的范围,行的这个版本对于其中的事务可见。一个事务可以看到所有小于xmin的事务的效果,这些事务确保已经被提交,但它无法看到任何大于等于xmax的事务的效果。

多语句事务还必须记录一个事务中哪个命令插入了一行(cmin)或者删除了一行(cmax),这样事务能够看到事务中先前的命令所作的更改。命令序列只在事务期间有意义,因此在一个事务开始时该序列被重置为0。

XID是数据库的一个性质。每一个Segment数据库都有其自己的XID序列,因此不能拿它和其他Segment数据库的XID进行比较。Master会使用一个集群范围的会话ID号来与Segment协调分布式事务,会话ID号被称为gp_session_id。Segment会会维护一个分布式事务ID到其本地XID的映射。Master用两阶段提交协议在所有Segment之间协调分布式事务。如果一个事务在任一一个Segment上失败,它将会在所有Segment上回滚。

用户可以用一个SELECT语句查看任意行的xmin、xmax、cmin和 cmax列:

因为用户是在Master上运行该SELECT命令,看到的XID都是分布式事务ID。如果用户能在一个Segment数据库上执行该命令,xmin和xmax值将是该Segment的本地XID。

事务ID回卷

MVCC模型使用事务ID(XID)来判断哪些行在一个查询或者事务开始时是可见的。XID是一个32位值,因此在该值溢出并且回卷到零之前,一个数据库理论上可以执行超过四十亿个事务。不过,Greenplum数据库使用模 232的计算方式来使用XID,这允许事务ID回卷,就像时钟会在十二点回卷一样。对于任何给定的XID,有大约二十亿个过去的XID和二十亿个未来的XID。直到一行的一个版本存在大约二十亿个事务之前,这一套机制都有效,当这种情况发生时那个版本就会突然变成一个新行。为了阻止这种情况的发生,Greenplum有一个被称为 FrozenXID的特殊XID,当把它和任何其他常规XID比较时它都是较老的哪一个。如果行中的xmin位于那二十亿个事务之中,就必须被替换为FrozenXID,这也是VACUUM命令执行的功能之一。

至少在每二十亿个事务时清理数据库可以阻止XID回卷。Greenplum数据库会监控事务ID并且在需要一次VACUUM操作时做出告警。

当不再可用的事务ID达到可观的比例并且事务ID回卷还没发生时,将会发出一个警告:

WARNING: database "database_name" must be vacuumed withinnumber_of_transactionstransactions

当该警告被发出时,就需要一次VACUUM操作。如果没有执行所需的VACUUM操作,当Greenplum数据库达到事务ID回卷发生之前的一个限制点时,它将会停止创建新事务来避免可能的数据丢失并且发出这样的错误:

FATAL: database is not accepting commands to avoid wraparound data loss in database "database_name"

关于从这种错误恢复的过程请见从一次事务ID限制错误中恢复(https://gp-docs-cn.github.io/docs/admin_guide/managing/maintain.html#topic3__np160654)。

服务器配置参数xid_warn_limit和 xid_stop_limit控制何时显示这些警告和错误。xid_warn_limit参数指定在xid_stop_limit之前多少个事务ID时发出警告。xid_stop_limit参数指定在回卷发生之前多少个事务ID时发出错误并且不允许创建新的事务。

事务隔离模式

SQL标准描述了数据库事务并发运行时可能发生的三种现象:

·脏读 – 一个事务可能读到来自另一个并发事务的未提交数据。

·不可重复读 – 在一个事务中两次读取同一行得到不同的结果,因为另一个并发事务在这个事务开始后提交了更改。

·幻读 – 在同一个事务中两次执行同一个查询可能返回不同的行集合,因为另一个并发事务增加了行。

SQL标准定义了数据库系统必须支持的四种事务隔离模式:

表 1. 事务隔离模式

Greenplum数据库的SQL命令允许用户请求READ UNCOMMITTED、 READ COMMITTED或者SERIALIZABLE。Greenplum数据库把READ UNCOMMITTED视作与READ COMMITTED相同。请求REPEATABLE READ会产生一个错误,请使用SERIALIZABLE代替。默认的隔离模式是READ COMMITTED。

READ COMMITTED和SERIALIZABLE之间的区别在于,在READ COMMITTED模式中,一个事务中的每个语句只能看到在该语句开始前提交的行,而在SERIALIZABLE模式中,一个事务中的所有语句都只能看到在该事务开始前提交的行。

The READ COMMITTED隔离模式允许比SERIALIZABLE模式更好的并发性和更好的性能。它允许不可重复读,也就是在一个事务中两次检索同一行的值可以不同,因为另一个并发事务在该事务开始后提交了修改。 READ COMMITTED模式也允许幻读,即在同一个事务中两次执行同一个查询可能返回不同的行集合。

SERIALIZABLE隔离模式能同时防止不可重复读以及幻读,但是其代价是并发度和性能。每一个并发事务都有一个取自其执行开始处的一致的数据库视图。一个尝试修改已被另一事务修改过的数据的并发事务将被回滚。如果一个应用执行的事务处于SERIALIZABLE模式中,它必须准备好处理事务由于序列化错误而失败的问题。如果应用不是非用SERIALIZABLE隔离模式不可,最好使用READ COMMITTED模式。

SQL标准定义并发可序列化事务产生的数据库状态和它们顺序执行时产生的数据库状态相同。MVCC快照隔离模型在没有使用昂贵的锁定方法的前提下,能阻止脏读、不可重复读和幻读。但是在Greenplum数据库中的某些SERIALIZABLE事务之间可能会出现其他相互作用,导致它们无法真正地可序列化。这些异常往往都是由于Greenplum数据库没有执行谓词逻辑锁导致,这意味着一个事务中的写操作可以影响另一个并发事务中先前的读操作的结果。

并发运行的事务应该接受检查以发现没有被禁止并发更新同一数据所阻止的相互作用。发现的问题可以通过使用显式表锁定或者要求冲突的事务更新一个表示该冲突的虚假行来阻止。

SQL语句SET TRANSACTION ISOLATION LEVEL为当前事务设置隔离模式。模式必须在任何SELECT、 INSERT、DELETE、UPDATE或者 COPY语句之前设置:

隔离模式也可以作为BEGIN语句的一部分指定:

一个会话的默认事务隔离模式可以通过设置default_transaction_isolation配置属性来修改。

从表中移除死亡的行

更新或者删除一行会在表中留下该行的一个过期版本。当一个过期的行不在被任何活跃事务引用时,它可以被移除从而腾出其所占用的空间进行重用。VACUUM命令会标记过期行所使用的空间可以被重用。

当表中的过期行累积后,为了容纳新的行就必须扩展磁盘文件。这样执行查询所需的磁盘I/O就会增加,从而性能受到影响。这种情况被称为膨胀,并且应该通过定期清理表来解决。

VACUUM命令(不带FULL)可以与其他查询并行运行。它会标记之前被过期行所占用的空间为空闲可用。如果剩余的空闲空间数量可观,它会把该页面加到该表的空闲空间映射中。当Greenplum数据库之后需要空间分配给新行时,它首先会参考该表的空闲空间映射以寻找有可用空间的页面。如果没有找到这样的页面,它会为该文件追加新的页面。

VACUUM(不带FULL)不会合并页面或者减小表在磁盘上的尺寸。它回收的空间只是放在空闲空间映射中表示可用。为了阻止磁盘文件大小增长,重要的是足够频繁地运行VACUUM。运行VACUUM的频率取决于表中更新和删除(插入只会增加新行)的频率。重度更新的表可能每天需要运行几次VACUUM来确保通过空闲空间映射能找到可用的空闲空间。在运行了一个更新或者删除大量行的事务之后运行VACUUM也非常重要。

VACUUM FULL命令会把表重写为没有过期行,并且将表减小到其最小尺寸。表中的每一页都会被检查,其中的可见行被移动到前面还没有完全填满的页面中。空页面会被丢弃。该表会被一直锁住直到VACUUM FULL完成。相对于常规的VACUUM命令来说,它是一种非常昂贵的操作,可以用定期的清理来避免或者推迟这种操作。最好是在一个维护期来运行VACUUM FULL。VACUUM FULL的一种替代方案是用一个CREATE TABLE AS语句重新创建该表并且删除掉旧表。

空闲空间映射位于共享内存中,它跟踪着所有表和索引的空闲空间。每一个表或者索引使用大约60字节的内存,每一个具有空闲空间的页面会使用6个字节。配置空闲空间映射尺寸的两个系统配置参数是:

max_fsm_pages

设置可以加入到共享空闲空间映射的磁盘页最大数量。每一个页槽需要消耗共享内存的6个字节。默认值是200000。这个参数必须被设置为max_fsm_relations值的至少16倍。

max_fsm_relations

设置共享内存中空闲空间映射所跟踪的关系的最大数量。这个参数应该被设置为一个大于表数量 + 索引数量 + 系统表数量总和的值。默认值为1000。在每个实例上每一个关系会消耗大约60字节的内存。这个参数值宜高不宜低。

如果空闲空间映射容量不足,一些具有可用空间的磁盘页将无法被加到其中,那么这些空间将无法被重用直至下一次VACUUM命令运行。这将会导致文件尺寸增长。

用户可以运行VACUUM VERBOSE tablename来得到一份Segment上已移除的死亡行数量、受影响页面数以及有可用空闲空间页面数的报告。

查询pg_class系统表可以找出一个表在所有Segment上使用了多少页面。注意首先对该表执行ANALYZE确保得到的是准确的数据。

另一个有用的工具是gp_toolkit方案中的gp_bloat_diag视图,它通过比较一个表使用的实际页数和预期的页数来确定表膨胀。更多有关gp_bloat_diag的内容请见Greenplum数据库参考指南中的“gp_toolkit管理方案”。

关于并行数据装载

这一主题给出了对于Greenplum数据库数据装载特性的简短介绍。

在一个大型的、具有数T字节的数据仓库中,必须在一个相对较小的维护窗口内完成对大量数据的装载。Greenplum支持使用其外部表特性的快速、并行数据装载。管理员也可以用单行错误隔离模式装载外部表,这样可以把有问题的行过滤到一个单独的错误表而继续装载正确格式的行。对于一次装载操作,管理员可以指定一个错误阈值以控制Greenplum在碰到多少不正确的行后中止装载操作。

通过结合外部表以及Greenplum数据库的并行文件服务器(gpfdist),管理员可以在他们的Greenplum数据库系统上达到最大的并行度和装载带宽。

图一. 外部表使用Greenplum并行文件服务器(gpfdist)

另一个Greenplum工具gpload能运行定义在一个YAML格式控制文件中的装载任务。在控制文件中描述了源数据位置、格式、转换要求、参与的主机、数据库目标以及其他说明,而gpload会执行装载。这允许用户描述一个复杂的任务,并且以可控、可重复的方式来执行它。

关于Greenplum数据库中的冗余和故障

这一主题给出了Greenplum数据库高可用性特性的一个高层次的概述。

用户可以利用镜像组件部署一个不会出现单点故障的Greenplum数据库。下面的小节描述了镜像Greenplum系统主要组件的策略。更多关于Greenplum高可用特性的详细介绍,请见Greenplum数据库高可用性概述(https://gp-docs-cn.github.io/docs/admin_guide/highavail/topics/g-overview-of-high-availability-in-greenplum-database.html#topic2)。

重要:当对于一个Greenplum数据库集群来说数据丢失不可接受时,Master和Segment的镜像必须被启用。如果没有镜像,系统和数据可用性就无法被保证。

关于Segment镜像

当用户在部署用户的Greenplum数据库系统时,用户可以配置镜像Segment。 如果主要的Segment变得不可用,镜像Segment允许数据库查询转移到一个备份的Segment上。对于生产系统我们强烈推荐做镜像。

二级(镜像)Segment必须总是放置于不同于其主要Segment的主机上,这样是为了防止单主机故障。在虚拟化环境下,二级(镜像)Segment必须总是位于一个与主要Segment不同的存储系统上。在一个为最大化可用性或者主机或者多个主要Segment失效时最小化性能衰退而设计的配置中,镜像Segment可以被分布在集群中剩下的主机上。

当用户在初始化或者扩展Greenplum系统时,可使用两种标准的镜像配置。默认的配置被称为组镜像,这种配置会把一个主机上的主要Segment的所有镜像都放置在集群中的其他一台主机上。还可以用一个命令行选项选择另一种标准配置 散布镜像,散布镜像会把每台主机的镜像散布到集群中剩余的主机上并且要求集群中的主机数量比每个主机上的主要Segment数量更多。

图1展示了当配置了散布镜像后,表数据如何分布在Segment之间。

图一. Greenplum数据库中的散布镜像

Segment故障切换和恢复

当Greenplum数据库系统中启用了镜像时,系统会在主要Segment变成不可用后自动切换到镜像Segment。 在一个Segment实例或者主机出问题的情况下,只要在剩余的活动Segment上的所有数据可用,Greenplum数据库系统就能保持可操作。

如果Master无法连接到一个Segment实例,它会在Greenplum数据库系统目录中标记该Segment实例为宕机并且把镜像Segment提升起来作为替代。失效的Segment实例将保持无法操作的状态直到管理员采取措施将它重新恢复上线。 gpstate工具可以被用来确定失效的Segment。管理员可以在系统运行时恢复失效的Segment。恢复进程只会复制该Segment无法操作期间错过的更改。

如果用户没有启用镜像,当一个Segment实例变得无效时整个系统将会自动关闭。在继续操作之前,用户必须恢复所有失效的Segment。

关于Master镜像

用户也可以选择性地在一台不同于Master节点的主机上部署一个Master实例的备份或者镜像。在主Master主机变得不可用时,一个备份Master主机将发挥温备的作用。后备Master利用事务日志复制进程保持与主Master同步,复制进程运行在后备Master上并且负责在主备Master主机之间同步数据。

如果主Master失效,日志复制进程会停止,并且后备Master会被激活以替代它的位置。这种切换不会自动发生,而是必须由外部触发。在激活后备Master时,将用已复制的日志来重构Master主机最后一次成功提交时的状态。被激活的后备Master实际会变成Greenplum数据库的Master,它会在主端口(在Master主机和备份Master主机上必须被设置为相同)上接受客户端连接。

由于Master不包含任何用户数据,只有系统目录表需要在主节点和备份节点之间同步。当这些表被更新时,更改会被自动地复制到后备Master以确保与主Master的同步。

图二. Greenplum数据库中的Master镜像

关于Interconnect冗余

Interconnect指的是Segment之间的进程间通信以及这种通信所依赖的网络设施。 通过在用户的网络上部署双千兆以太网交换机以及到Greenplum数据库主机(Master和Segment)服务器的冗余千兆连接,用户可以得到非常可靠的Interconnect。处于性能的原因,我们推荐10-Gb以太网或者更快的网络。

关于Greenplum数据库中的数据库统计信息

Greenplum数据库中通过ANALYZE命令收集的统计信息的概述。

统计信息是描述数据库中数据的元数据。查询优化器需要最新的统计信息以便为查询选择最好的执行计划。例如,如果一个查询连接两个表并且其中的一个必须被广播到所有的Segment,优化器可以选择两个表中较小的那一个来最小化网络流量。

优化器使用的统计信息由ANALYZE命令计算并且保存在系统目录中。有三种方式开始一个分析操作:

·用户可以直接运行ANALYZE命令。

·用户可以在数据库外部从命令行运行analyzedb管理工具。

·当在没有统计信息的表上执行DML操作或者一个DML操作修改的行数超过指定阈值时,会触发一次自动的分析操作。

这些方法会在下面的小节中描述。VACUUM ANALYZE命令是另一种启动分析操作的方式,但是不鼓励使用它,因为清理和分析是两种不同目的的不同操作。

计算统计信息需要消耗时间和资源,因此Greenplum数据库通过在大型表的采样上计算统计信息来得到估计值。在大部分情况下,默认的设置提供了足以为查询生成正确执行计划的信息。如果产生的统计信息没有产生最优的查询执行计划,管理员可以调节配置参数通过提高样本尺寸或者系统目录中保存的统计信息粒度来产生更准确的统计信息。产生更准确的统计信息需要CPU和存储代价并且不一定能产生更好的计划,因此重点是查看解释计划并且测试查询性能来确保额外的统计信息代价能导致更好的查询性能。

系统统计信息

表尺寸

查询规划器想要最小化执行查询所需的磁盘I/O和网络流量,它会使用必须被处理的行数以及查询必须访问的磁盘页面数的估计值。用于生成这些估计值的数据是pg_class系统表列reltuples和relpages,它们分别包含上一次VACUUM或ANALYZE命令运行时的行数和页面数。随着行被增加或删除,这些数字变得越来越不准确。不过,总是可以从操作系统拿到准确的磁盘页面计数,因此只要reltuples与relpages的比例不发生显著变化,优化器就能够产生对选择正确的查询执行计划足够准确的行数估计。

当reltuples列与SELECT COUNT(*)返回的行计数显著不同时,应该执行一次分析来更新统计信息。

当一个REINDEX命令完成了重建一个索引时,relpages和reltuples列被设置为零。应该在基表上运行ANALYZE命令以更新这些列。

pg_statistic系统表和pg_stats视图

pg_statistic系统表保持在每个数据库表上最后一次ANALYZE操作的结果。其中为每一个表的每一列都有一行。行有下面的列:

starelid

该列所属的表或索引的对象ID。

staatnum

所描述列的编号,从1开始。

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组成。

stakindN列每个包含一个数字代码来描述存储在它们的槽中的统计信息类型。stakind代码数字从1到99被保留给核心的PostgreSQL数据类型。Greenplum数据库使用代码数字1、2以及3。值0表示槽未被使用。下面的表格描述了为三种代码存储的统计信息类型。

表 1. pg_statistic中"槽"的内容

pg_stats视图以一种友好的格式表示pg_statistic的内容。pg_stats视图有下列列:

schemaname

包含该表的方案名称。

tablename

该表的名称。

attname

这行所描述的列名。

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 TABLEtable 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数据库不计算相关关系统计信息。

新创建的表和索引没有统计信息。可以用gp_stats_missing视图检查缺少统计信息的表,该视图位于gp_toolkit方案中:

采样

在为大型表计算统计信息时,Greenplum数据库通过采样基表来创建一个较小的表。如果表被分过区,会从所有的分区取得抽样。

如果基表中的行数被估计为小于gp_statistics_sampling_threshold配置参数的值,整个基表都会被用来计算统计信息。

如果一个采样表被创建,会计算采样中的行数来提供一个最大可接受相对误差。可接受误差的量由gp_analyze_relative_error系统配置参数指定,默认它被设置为.25 (25%)。这通常对生成正确的查询计划已经足够准确。如果ANALYZE没有为一个表列产生好的估计,可以通过设置gp_analyze_relative_error配置参数为一个较低的值以增加采样尺寸。注意将这个参数设置为较低的值可能导致非常大的采样尺寸并且急剧增加分析时间。

更新统计信息

运行不带参数的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要求在分区表根层的统计信息。传统优化器不使用这些统计信息。通过同时设置optimizer和optimizer_analyze_root_partition系统配置参数为on可以启用GPORCA。接着当用户运行ANALYZE或者ANALYZE ROOTPARTITION时,根层统计信息会被更新。运行ANALYZE ROOTPARTITION的时间类似于分析具有相同数据的未分区表,因为ANALYZE ROOTPARTITION不收集叶子分区上的统计信息只采样数据。analyzedb工具默认会更新根分区统计信息,但用户在没有使用GPORCA时可以增加--skip_root_stats选项让根分区统计信息留空。

配置统计信息

有几个选项可以配置Greenplum数据库的统计信息收集。

统计信息目标

统计信息目标是一个列的most_common_vals、most_common_freqs以及histogram_bounds数组的尺寸。默认情况下,目标是25。默认目标可以通过设置一个服务器配置参数来更改,对任意列可以使用ALTER TABLE命令设置目标。较大的值会增加执行ANALYZE所需的时间,但是可能会增加传统查询优化器(规划器)估计值的质量。

可以通过设置default_statistics_target服务器配置参数将系统的默认统计信息目标设置为一个不同的值。默认值通常是足够的,用户只应该在测试证明新的目标能够改进查询计划时才调整目标。例如,要将默认的统计信息目标从25增加到50,用户可以使用gpconfig工具:

个体列的统计信息目标可以用ALTER TABLE命令设置。例如,通过为特定列(特别是具有不规则分布的列)增加该目标可以改进一些查询。用户可以将从不对查询优化做出贡献的列的目标设置为零。当目标为0时,ANALYZE会忽略该列。例如,下面的ALTER TABLE命令把emp表中的notes列的统计信息目标设置为零:

统计信息目标可以被设置为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模式可能会触发大型的、预期之外的分析操作,它们可能会中断系统,因此不推荐在全局范围内设置它。在一个会话中它可能会有用,例如在一次装载后自动分析一个表。

要在函数之外禁用自动统计收集,将gp_autostats_mode参数设置为none:

要在函数中为没有统计信息的表启用自动统计收集,将gp_autostats_mode_in_functions改成on_no_stats

如果想要记录自动统计收集操作,可将log_autostats系统配置参数设置为on。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180321A0ZWKY00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券