greenplum架构介绍
Posted Serendipity_Shy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了greenplum架构介绍相关的知识,希望对你有一定的参考价值。
1 Greenplum 简介
GreenPlum是一款基于分布式架构的开源数据库;采用无共享(no shareing)的MPP架构(每个数据节点拥有独立的CPU、IO和内存等资源);其具有良好的线性扩展能力,具有高效的并行运算、并行存储特性。拥有独特的高效的ORCA优化器。非常适合用于PB数据量级的存储、处理和实时分析能力。Greenplum是基于PostgreSQL数据库发展而来,本质上是多个PostgreSQL面向磁盘的数据库实例一起工作形成的一个紧密结合的数据库管理系统(DBMS),同时支持涵盖OLTP型业务混合负载,数据节点和主节点均可设计备份节点,进而提供数据库的高可用性。
2 Greenplum架构
如上图,Greenplum由Master节点<协调节点>和Segment节点<数据节点>以及高速网络层三部分组成,转载自官网Greenplum的架构。
- Master Host: 又称协调节点,是整个Greenplum数据库系统的入口。负责接受来自客户端连接请求,对SQL语句生成查询计划,并将查询计划分发至涉及的Segment实例上,收集Segment实例返回的结果并呈现给客户端。同时Master记录集群中的元数据信息,包括各种全局系统系统表,但Master上不存储任何用户数据,数据只存在于Segment之上。
- Standby: Master的备库,在Master 发生故障不可提供服务时可promote Standby继续提供服务,保证集群的高可用,正常情况下Standby上进行只读操作,且时时同步Master的元数据。
- Segment Host【Primary segment】:数据节点,其功能是存放并管理数据库中的数据,接收Master分发下来的执行计划,执行返回结果给Master节点。
- Mirror segment: Primary segment节点的备库以保障高可用性;通常跟对应的Primary segment节点不在同一台机器上。在segment节点出现故障,mirror segment自动接管进行工作。但是为了数据库平稳;尽快恢复出现故障的segment。
- Interconnet: Interconect是Greenplum数据库架构中的网络层,是Segment之间的进程间通信以及这种通信所依赖的网络基础设施。 Greenplum的Interconnect使用带流控制的用户数据包协议(UDPIFC)在网络上发送消息,可靠性和可扩展性超于TCP。 之所以采用UDP,是因为Interconnect改为TCP,当Segment实例超过1000个时其可扩展性会受到限制,而对于Interconnect的默认协议UDPIFC则不存在这种限制。
3 Greenplum特性
- 超大规模和高性能:Greenplum数据库采用超大规模无共享MPP架构,将多台服务器组成一个强大计算平台,实现高效的海量并行计算。同时在查询优化方面。Greenplum不仅支持PostgreSQL的查询优化器外,还开发一个新的查询优化器ORCA。ORCA是一款自顶向下的基于Cascades框架的查询计划器,相比PostgreSQL查询优化器而言,其性能能够提升 10 -1000倍。
- 高可用:Greenplum提供多级容错机制确保整个集群的高可用。对与Master节点,设计Standby master进行元数据的备份,每个Primary segment 分别可以配置若干个Mirror segment进行备份,同时确保同一组的Primary segment 与Mirror segment 节点不在同一物理机,从而减小由于宕机等意外故障导致的数据丢失分险。
- 通用性:Greenplum数据库支持完善的SQL标准。同时。由于Greenplum基于PostgreSQL数据库开发,因此继承了PostgreSQL对于JDBC/OBJC/C/Python API等接口的支持。
- 多态存储:Greenplum数据库提供“多态存储”的灵活存储方式。用户可以根据数据热度或者访问模式的不同使用不同的存储方式,以获取的更好的查询性能。用户可以将一张表按照一定规则[日期]分成若干个分区,不同的分区可以使用不同的物理存储方式。支持存储方式包括:1)行存储,数据以行的形式存储在数据页里,适合频繁的更新;2)列存储,数据以列的形式存放在数据页中,适合OLAP分析性场景;3)外部表,数据保存在外部文件,比如HDFS、S3等,数据库只保持元数据信息。
- 高扩展和高效资源管理:得益于MPP无共享架构,Greenplum具有良好的线性扩展能力。用户可以通过水平扩展增加硬件资源提升数据存储和计算能力。同时Grennplum还提供高效的资源管理机制,根据用户的业务逻辑将资源合理分配给查询任务,避免查询因资源不足而得不到相应,主要是通过对并发查询数目的限制、查询执行内存占用、CPU资源使用情况进行一定约束。提供两种资源管理方式:资源队列和资源组,详见greenplum官网。
- 高效数据加载:Grennplum采用MPP架构可以高地并行家在数据,即允许数据从多个文件系统通过多个主机上的多个网卡进行加载,达到高效数据传输效率。Greenplum支持多重读入和写入数据源,包括文件文本、XML文件、HDFS、Kafka和Spark等,同时还支持数据压缩。
总结
Greenplum数据库是领先的基于MPP架构的开源分布式数据库,具有良好的弹性和线性扩展能力,内置并行存储+通信+计算和优化技术,高度兼容SQL标准,具备强大高效的PB级数据存储、处理和实时分析能力。目前广泛用于ETL、商业智能、高级分析、GIS数据处理、机器学习等领域。
Greenplum 架构详解 & Hash Join 算法介绍
Greenplum数据库是一种大规模并行处理(MPP)数据库服务器,其架构特别针对管理大规模分析型数据仓库以及商业智能工作负载而设计。
MPP(也被称为shared nothing架构)指有两个或者更多个处理器协同执行一个操作的系统,每一个处理器都有其自己的内存、操作系统和磁盘。 Greenplum使用这种高性能系统架构来分布数T字节数据仓库的负载并且能够使用系统的所有资源并行处理一个查询。
Greenplum数据库是基于PostgreSQL开源技术的。它本质上是多个PostgreSQL面向磁盘的数据库实例一起工作形成的一个紧密结合的数据库管理系统(DBMS)。 它基于PostgreSQL 9.4开发,其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负责存储和处理数据。
Figure 1. 高层的Greenplum数据库架构
image下面的主题描述了组成一个Greenplum数据库系统的组件以及它们如何一起工作。
Parent topic: Greenplum数据库概念
关于Greenplum的Master
Greenplum数据库的Master是整个Greenplum数据库系统的入口,它接受连接和SQL查询并且把工作分布到Segment实例上。
Greenplum数据库的最终用户与Greenplum数据库(通过Master)交互时,会觉得他们是在与一个典型的PostgreSQL数据库交互。 他们使用诸如<samp class="ph codeph" style="-webkit-font-smoothing: antialiased; box-sizing: border-box; font-family: monospace, monospace; font-size: 1em;">psql</samp>之类的客户端或者JDBC、ODBC、 libpq(PostgreSQL的C语言API)等应用编程接口(API)连接到数据库。
Master是全局系统目录的所在地。全局系统目录是一组包含了有关Greenplum数据库系统本身的元数据的系统表。 Master上不包含任何用户数据,数据只存在于Segment之上。 Master会认证客户端连接、处理到来的SQL命令、在Segment之间分布工作负载、协调每一个Segment返回的结果以及把最终结果呈现给客户端程序。
Greenplum数据库使用预写式日志(WAL)来实现主/备镜像。 在基于WAL的日志中,所有的修改都会在应用之前被写入日志,以确保对于任何正在处理的操作的数据完整性。
Note: Segment镜像还不能使用WAL日志。
关于Greenplum的Segment
Greenplum数据库的Segment实例是独立的PostgreSQL数据库,每一个都存储了数据的一部分并且执行查询处理的主要部分。
当一个用户通过Greenplum的Master连接到数据库并且发出一个查询时,在每一个Segment数据库上都会创建一些进程来处理该查询的工作。 更多有关查询处理的内容,请见关于Greenplum的查询处理。
用户定义的表及其索引会分布在Greenplum数据库系统中可用的Segment上,每一个Segment都包含数据的不同部分。 服务于Segment数据的数据库服务器进程运行在相应的Segment实例之下。 用户通过Master与一个Greenplum数据库系统中的Segment交互。
Segment运行在被称作Segment主机的服务器上。 一台Segment主机通常运行2至8个Greenplum的Segment,这取决于CPU核数、RAM、存储、网络接口和工作负载。 Segment主机预期都以相同的方式配置。 从Greenplum数据库获得最佳性能的关键在于在大量能力相同的Segment之间平均地分布数据和工作负载,这样所有的Segment可以同时开始为一个任务工作并且同时完成它们的工作。
关于Greenplum的Interconnect
Interconect是Greenplum数据库架构中的网络层。
Interconnect指的是Segment之间的进程间通信以及这种通信所依赖的网络基础设施。 Greenplum的Interconnect采用了一种标准的以太交换网络。出于性能原因,推荐使用万兆网或者更快的系统。
B默认情况下,Interconnect使用带流控制的用户数据包协议(UDPIFC)在网络上发送消息。 Greenplum软件在UDP之上执行包验证。这意味着其可靠性等效于传输控制协议(TCP)且性能和可扩展性要超过TCP。 如果Interconnect被改为TCP,Greenplum数据库会有1000个Segment实例的可扩展性限制。对于Interconnect的默认协议UDPIFC则不存在这种限制。
Greenplum 的查询处理
这个主题给出了Greenplum数据库如何处理查询的概述。理解这一处理有助于编写和调优查询。
用户像对任何数据库管理系统那样将查询发送到Greenplum数据库。它们使用psql之类的客户端应用连接到Greenplum的Master主机上的数据库实例并且提交SQL语句。
Master接收、解析并且优化查询。作为结果的查询计划可能是并行的或者定向的。如图 Figure 1所示,Master会把并行查询计划分发到所有的Segment。而如图 2Figure 2所示,Master会把定向查询计划分发到单一的一个segment实例。每个segment实例负责在其自己的数据集上执行本地数据库操作。
大部分的数据库操作(例如表扫描、连接、聚集和排序)都会以并行的方式在所有segment实例上执行。在一个segment实例的数据库上执行的每个操作都独立于存储在其他segment实例数据库中的数据。
Figure 1. 分发并行查询计划
image某些查询可能只访问单个Segment上的数据,例如单行的INSERT, UPDATE, DELETE, 或者 SELECT操作或者以表分布键列过滤的查询。在这些查询中,segment实例,而是定向给到包含受影响或者相关行的segment实例。
Figure 2. 分发定向查询计划
image理解Greenplum的查询计划
查询计划是Greenplum数据库将要执行以产生查询答案的操作集合。计划中的每个节点或者步骤表示一个数据库操作,例如表扫描、连接、聚集或者排序。计划的读取和执行按照从底向上的顺序进行。
除通常的数据库操作(例如表扫描、连接等等)之外,Greenplum数据库还有一种额外的被称为移动的操作类型。移动操作涉及到在查询处理期间在segment实例之间移动元组。注意并非每一个查询都需要移动操作。例如,定向查询计划就不需要通过Interconnect移动数据。
为了在查询执行期间达到最大并行度,Greenplum将查询计划的工作划分成切片。切片是Segment能够在其上独立工作的计划片段。只要有一个移动操作出现在计划中,该查询计划就会被切片,在移动的两端分别有一个切片。
例如,下面涉及两个表之间连接的简单查询:
SELECT customer, amount
FROM sales JOIN customer USING (cust_id)
WHERE dateCol = '04-30-2016';
Figure 3 展示了这个查询计划。每个segment实例接收一份查询计划的拷贝并且并行地根据计划工作。
这个例子的查询计划有一个重分布移动,它在segment实例之间移动元组以完成连接。重分布移动是必要的,因为customer表在Segment上按照cust_id分布,而sales表是按照sale_id分布。为了执行该连接,sales元组必须按照cust_id重新分布。该计划在重分布移动操作的两边被切换,形成了slice 1和slice 2。
这个查询计划由另一种称为收集移动的移动操作。收集操作表示segment实例何时将结果发回给Master,Master再将结果呈现给客户端。由于只要有移动产生查询计划就会被切片,这个计划在其最顶层也有一个隐式的切片(slice 3)。不是所有的查询计划都涉及收集移动。例如,一个CREATE TABLE x AS SELECT...语句不会有收集移动,因为元组都被发送到新创建的表而不是发给Master。
Figure 3. 查询切片计划
image.png理解并行查询执行
术语说明:
查询分发器(QD)
查询执行器(QE)
Greenplum会创建若干数据库进程来处理查询的工作。在Master上,查询工作者进程被称作查询分发器(QD)。QD负责创建并且分发查询计划。它也收集并且表达最终的结果。在Segment上,查询工作者进程被称为查询执行器(QE)。
QE负责完成它那一部分的工作并且与其他工作者进程交流它的中间结果。
对查询计划的每一个切片至少要分配一个工作者进程。工作者进程独立地工作在分配给它的那部分查询计划上。在查询执行期间,每个Segment将有若干进程并行地为该查询工作。
为查询计划的同一个切片工作但位于不同Segment上的相关进程被称作团伙。随着部分工作的完成,元组会从一个进程团伙流向查询计划中的下一个团伙。这种Segment之间的进程间通信被称作Greenplum数据库的Interconnect组件。
Figure 4 所示查询计划在Master和两个Segment实例上的查询工作者进行。
Figure 4. 查询工作者进程
image.pngTips: hash join
hash join是一种数据库在进行多表连接时的处理算法,对于多表连接还有两种比较常用的方式:sort merge-join 和 nested loop。
多表连接的查询方式又分为以下几种:内连接,外连接和交叉连接。外连接又分为:左外连接,右外连接和全外连接。对于不同的查询方式,使用相同的join算法也会有不同的代价产生,这个是跟其实现方式紧密相关的,需要考虑不同的查询方式如何实现,对于具体使用哪一种连接方式是由优化器通过代价的衡量来决定的,后面会简单介绍一下几种连接方式代价的计算。 hashjoin其实还有很多需要考虑和实现的地方,比如数据倾斜严重如何处理、内存放不下怎木办,hash如何处理冲突等。
nested loop join
嵌套循环连接,是比较通用的连接方式,分为内外表,每扫描外表的一行数据都要在内表中查找与之相匹配的行,没有索引的复杂度是O(N*M),这样的复杂度对于大数据集是非常劣势的,一般来讲会通过索引来提升性能。
sort merge-join
merge join需要首先对两个表按照关联的字段进行排序,分别从两个表中取出一行数据进行匹配,如果合适放入结果集;不匹配将较小的那行丢掉继续匹配另一个表的下一行,依次处理直到将两表的数据取完。merge join的很大一部分开销花在排序上,也是同等条件下差于hash join的一个主要原因。
原理和实现
简单的对于两个表来讲,hash-join就算讲两表中的小表(称S)作为hash表,然后去扫描另一个表(称M)的每一行数据,用得出来的行数据根据连接条件去映射建立的hash表,hash表是放在内存中的,这样可以很快的得到对应的S表与M表相匹配的行。
对于结果集很大的情况,merge-join需要对其排序效率并不会很高,而nested loop join是一种嵌套循环的查询方式无疑更不适合大数据集的连接,而hash-join正是为处理这种棘手的查询方式而生,尤其是对于一个大表和一个小表的情况,基本上只需要将大小表扫描一遍就可以得出最终的结果集。
不过hash-join只适用于等值连接,对于>, <, <=, >=这样的查询连接还是需要nested loop这种通用的连接算法来处理。如果连接key本来就是有序的或者需要排序,那么可能用merge-join的代价会比hash-join更小,此时merge-join会更有优势。
好了,废话说了不少了,来讲讲实现,拿一条简单的多表sql查询语句来举个栗子:select * from t1 join t2 on t1.c1 = t2.c1 where t1.c2 > t2.c2 and t1.c1 > 1。这样一条sql进入数据库系统中,它是如何被处理和解剖的呢?sql:鬼知道我都经历了些什么。。。
1.背景知识
1.第一步呢,它需要经历词法以及语法的解析,这部分的输出是一颗带有token结点的语法树。
image语法分析,顾名思义这部分只是语法层面的剖析,将一个string的sql语句处理成为一颗有着雏形结构的node tree,每个结点有它们自身的特殊标识,但是并没有分析和处理这个结点的具体含义和值。
2. 第二步是语义分析和重写处理。
重写的过程不同的数据库可能有不同的处理,有些可能是跟逻辑执行过程放在一起,有的则分开。
image这一步做完树的形状大体上是与语法分析树保持一致的,但是此时的结点都携带了一些具体的信息,以where后面的表达式为例,这颗中缀表达式每一个结点都有了自身的类型和特定的信息,并不关心值是什么,这步做完后进入改写过程,改写是一种逻辑优化方式,使得一些复杂的sql语句变得更简单或者更符合数据库的处理流程。
3.优化器处理
优化器的处理是比较复杂的,也是sql模块最难的地方,优化无止境,所以优化器没有最优只有更优。优化器需要考虑方方面面的因素既要做的通用型很强又要保证很强的优化能力和正确性。
优化器最重要的作用莫过于路径选择了,对于多表连接如何确定表连接的顺序和连接方式,不同的数据库有着不同的处理方式,pg支持动态规划算法,表数量过多的时候使用遗传算法。路径的确定又依赖于代价模型的实现,代价模型会维护一些统计信息,像列的最大值、最小值、NDV和DISTINCT值等,通过这些信息可以计算选择率从而进一步计算代价。
image回归到正文,使用哪一种连接方式就是在这里决定的,hash join 对大小表是有要求的,所以这里形成的计划是t1-t2还是t2-t1是不一样的,每种连接方式有着自身的代价计算方式。
hash join的代价估算:
COST = BUILD_COST + M_SCAN_COST + JOIN_CONDITION_COST + FILTER_COST
简单来看,hash join的代价主要在于建立hash表、扫描M表、join条件连接和filter过滤,对于S表和M表都是只需要扫描一次即可,filter过滤是指t1.c2>t2.c2这样的条件过滤,对于t1.c1>1这样只涉及单表的条件会被下压,在做连接之前就被过滤了。
优化器处理过后,会生成一颗执行计划树,真正的实现过程根据执行计划的流程操作数据,由低向上地递归处理并返回数据。
image2.hash join的实现
hash join的实现分为build table也就是被用来建立hash map的小表和probe table,首先依次读取小表的数据,对于每一行数据根据连接条件生成一个hash map中的一个元組,数据缓存在内存中,如果内存放不下需要dump到外存。依次扫描探测表拿到每一行数据根据join condition生成hash key映射hash map中对应的元組,元組对应的行和探测表的这一行有着同样的hash key, 这时并不能确定这两行就是满足条件的数据,需要再次过一遍join condition和filter,满足条件的数据集返回需要的投影列。
imagehash join实现的几个细节
1.hash join本身的实现不要去判断哪个是小表,优化器生成执行计划时就已经确定了表的连接顺序,以左表为小表建立hash table,那对应的代价模型就会以左表作为小表来得出代价,这样根据代价生成的路径就是符合实现要求的。
2.hash table的大小、需要分配多少个桶这个是需要在一开始就做好的,那分配多少是一个问题,分配太大会造成内存浪费,分配太小会导致桶数过小开链过长性能变差,一旦超过这里的内存限制,会考虑dump到外存,不同数据库有它们自身的实现方式。
3.如何对数据hash,不同数据库有着自己的方式,不同的哈希方法也会对性能造成一定的影响。
参考资料
https://www.cnblogs.com/shangyu/p/6055181.htmlhttp://docs-cn.greenplum.org/v6/admin_guide/query/topics/parallel-proc.html#topic1
以上是关于greenplum架构介绍的主要内容,如果未能解决你的问题,请参考以下文章