一般地,greenplum的每个segment节点对应一个网口NIC,一个物理CPU,一个磁盘控制器,以便同机器的多个segment之间互不影响。
greenplum的备份,提供了gp_dump做并行备份,master和segment节点同时执行备份操作,另外gp_crondump会定期执行备份操作;
支持PostgreSQL的pg_dump和pg_dumpall命令,但是其将所有的数据写成一个文件保存在master上,使用受限。
(在白皮书的第21章节备份与恢复有详细描述)
在master节点的$MASTER_DATA_DIRECTORY目录下,pg_hba.conf文件保存了主机远程访问策略;postgresql.conf文件配置了数据库运行的参数。
greenplum数据库的启动gpstart,关闭gpstop,重启gpstop -r,强制关闭gpstop -f ,修改参数后不重启DB加载参数gpstop -u ,仅启动mastergpstart -m;
在master节点修改postgresql.conf文件,想所有segment同时修改postgresql.conf文件的操作是:
gpssh -f ~/seg_hosts "echo 'parameter=value' | cat - >> /gpdata/p*/*/postgresql.conf"
--------------------------------------------------------------------------------------------------------------
用greenplum实现mapreduce:
INPUT部分将输入拆分成(key,value)对儿,送给MAP部分;MAP部分将其生成新的(key,output_list)对儿,然后送给reduce部分;由reduce部分安照key分组运算得到结果。
比如INPUT的输入时text文件,输出是(NULL,行),MAP的输出是(单词,个数),REDUCE的输出是(单词,汇总个数)。
输入的数据可以是多种文件格式的文件以及数据库中的数据,MAP和REDUCE部分的函数自定义,REDUCE也可以用内置的函数,OUTPUT可以写入数据库、标准输出或文件。注意,在编程时,INPUT的结果只有列的概念,而没有key的概念,以行为单位发送给每个MAP,在MAP中定义的输出的key才是真正的key,REDUCE正是靠这个key执行操作的,当然REDUCE也可以声明KEYS都包括哪些入参。
详细的,INPUT函数的源的关键词可以是FILE/GPFDIST/TABLE/QUERY/EXEC,如果没指定COLUMNS,那么默认认为整个文件只有一列。MAP函数的输入和输出都是key/value形式的text类型,除非指定PARAMETERS和RETURNS声明,LANGUAGE声明了用perl还是python语言,如果一次MAP函数会有多个返回值就用yield,否则要声明MODE为SINGLE,返回注意yield的用法(执行到此返回,下次执行函数时从yield的下一句开始执行,可用来循环追加数据列表)。另外,gpmapreduce命令可以通过-k参数指定key值,作为map的入参key。
REDUCE有一些内置函数,比如IDENTITY/SUM/AVG/COUNT/MIN/MAX,这些内置函数的入参名称是key和value。REDUCE实现与MAP实现相比略微复杂,因为它需要考虑将多条返回记录合并,因此需要在REDUCE函数里面定义一次迁移(TRANSITION)函数,还需要定义FINALIZE函数,初始化参数INITIALIZE,以及可选的合并函数CONSOLIDATE。每个REDUCE的输入对应一个迁移,为了记录当前迁移的位置,迁移函数需要定义变量state,由INITIALIZE赋初值,每次TRANSITION的返回值就是下一次TRANSITION的state输入,进行按key分类的每个key下所有输入的迁移,当最后一条输入在迁移中处理完后,将state值传递给FINALIZE函数,触发FINALIZE工作,返回多个结果。REDUCE的参数一般还是key/value,而传给迁移函数的参数一般是state/value。可选函数CONSOLIDATE的作用是将多个state合并为一个。REDUCE的输出不仅可以是标准输出,还可以是数据库表TABLE或文件FILE。要是往数据库里写的话,需要指定TABLE标识,同时MODE标识指定为APPEND或REPLACE,含义是追加或重写,建表的分布默认是REDUCE的keys,也可以指定标识KEYS以重新分布。特别注意如果输出是FILE的话,文件不能已存在。
对于有的大型任务来说,一级mapreduce是不行的,多级mapreduce需要TASK支持,每个TASK一般是一个完整的INPUT-MAP-REDUCE过程,然后作为下一级INPUT的输入出现(一条条记录的结果集,类似select的结果)。
在数据库中创建解析mapreduce的语言:
psql -c 'CREATE LANGUAGE plpythonu;'
psql -c 'CREATE LANGUAGE plperl;'
对于用python写代码遇到莫名错误的问题,可以在函数中添加异常处理信息,打印plpy.warning(e)可以提高调试速度。
YAML不支持TAB对齐,只能用空格对齐。
------------------------------------------------------------------------------------------------------------------------------------
系统架构——冗余和镜像:
基于PostgreSQL 8.2.13,内部修改以支持并行结构,segments上保存数据,节点间内部通信默认采用UDP协议,用额外的packet负责控制信息,代替TCP协议且取得不错的效果。
segment镜像和segment一定保存在不同的host上,master如果连不上segment,就把它标记为invalid状态,如果下次连上了,就重置为valid状态。如果系统没配置镜像,那么master在检测到invalid的segment时就会关闭数据库,来保证数据不出错;如果系统配置了镜像,那么系统在read-only模式和continue模式下的处理方式是不同的,前者不允许DDL和DML操作,可在线恢复,后者的操作必须限制在非invalid的segment上的数据,而且invalid的segment恢复时必须重启数据库系统。
master镜像就是master的在线standby,因为master上面只保存目录表和系统日志,因此在standby上面有一个事务重复记录进程(gpsyncagent)连接master以同步,一旦master连不上即坏掉,该进程停止工作,并让standby从master上一个成功事务操作之后开始接管系统(PS:master出故障前,standby上面只有gpsyncagent一个进程运行)。
互连冗余,意指每个segment至少双网卡,一用网络连接,二用内部数据传输,提高通信可靠性。
(详细参考白皮书的第五章系统管理的高可用性章节)
系统架构——数据并行加载
通过外部表(external table),使用并行文件服务器(gpfdist),可实现并行的数据加载。策略是M:N,即每个segment都会去连接每个gpfdist服务器。可通过postgresql.conf配置文件的gp_external_max_segs参数调整连接一个gpfdist服务器的segments个数,默认是64。
换句话说,external tables就是数据库将text文件按照列分割展示为数据库表的形式,可以执行select、join、sort这样的SQL操作了,相当于ETL的“抽取”部分。当然这个表是read-only的,不能执行DML操作,也不能建索引,并且数据展示依赖于gpfdist服务进程的存在。最后可以用CREATE TABLE X AS SELECT和INSERT INTO SELECT这样的语句实现ETL的“加载”部分,在加载的性能上,要考虑以下3点:先导入后建索引;导入后执行analyze更新query planner记录的信息;导入时遇到错误的话,最后要执行vacuum,用来释放失败的导入操作占用的空间。
系统架构——管理和监视
简单说,管理包括从数据库安装到数据并行加载的很多命令,都保存在$GPHOME/bin目录下。
要想对greenplum进行性能监视,就要在每个host上安装一个agent,一般每15秒采集一次数据,发送到master上。
系统架构——分布式存储
master上只保存全局目录表,而数据都保存在segment上面,对于每一个表在创建时都要制定distributed策略,将满足不同策略的rows分别保存在不同的segment上面。distributed策略有两种,hash和random两种方式,默认是hash分布。对于hash分布,一般选取主键作用的列作为分布依据,如果没指定列,那么默认是主键作用的列,否则是第一列。随机分布就是将数据随机保存在不同的segment上面,在所有segment上面进行全表扫描这样的操作时,由于IO时间均摊,是个效率很高的方法。
---------------------------------------------------------------------------------------------------------------------------------------
与SQL标准比较,当前(截止3.3.5版本,测试版本3.2)存在的问题:
1.不支持对hash分布的key列做update操作,因为不支持hash列重分布后行数据在segments之间迁移。
2.UPDATE and DELETE statements that require data to move from one segment to another. This restricts the use of joins in update and delete operations to hash-distributed tables that have the same distribution key column(s), and the join condition must specify equality on the distribution key column(s).
——join的连接条件必须是DT列,否则需要列重分布。(确定了join的连接条件,就是确定了segments之间的连接)
3.Correlated subqueries that Greenplum’s parallel optimizer cannot internally rewrite into non-correlated joins. Most simple uses of correlated subqueries do work. Those that do not can be manually rewritten using outer joins.
——内部优化的时候,相关子查询不能重写到非相关连接里面。对于不能正常工作的相关子查询,需要手动改写到外连接里面。
4.Certain rare cases of multi-row subqueries that Greenplum’s parallel optimizer cannot internally rewrite into equijoins.
——内部优化的时候,某些罕见的多行子查询不能写成equi-join(用相等来连接的,join .. on =)的形式。
5.内部优化的时候,一些在EXISTS或NOT EXISTS子查询子句中返回的集合不能重写成连接(join)。
6.不支持子查询中UNION所有的joined tables。
7.不支持子查询中在FROM子句中返回集合函数。
8.不支持退滚游标,比如使用FETCH PRIOR,FETCH FIRST,FETCH ABSOLUTE,FETCH RELATIVE。
9.hash分布建表时,UNIQUE或PRIMARY KEY子句应该包含所有的DT列,并且建表时只能写UNIQUE子句或PRIMARY KEY子句中的一个。如果是random分布的建表,就不能写UNIQUE或PRIMARY KEY子句了。
10.CREATE UNIQUE INDEX的时候,一定要覆盖所有的DT列。random分布的不能使用该语句。
11.VOLATILE or STABLE functions cannot execute on the segments, and so are generally limited to being passed literal values as the arguments to their parameters.
——一些函数不能直接在segment上执行,因此限制了将字面的值传递给参数。
12.不支持触发器,因为他们依赖VOLATILE函数。
13.不强制外键约束,用户定义的外键是保存在system catalog上面的。
14.不支持序列操作函数CURRVAL和LASTVAL。
15.不支持DELETE WHERE CURRENT OF和UPDATE WHERE CURRENT OF。
不支持SQL92的特性,包括:
1.字符类型只有CHAR和VARCHAR,而不支持NCHAR或NVARCHAR类型。
2.不支持CREATE ASSERTION语句。
3.支持INTERVAL关键字,但是没依照标准。
4.不支持GET DIAGNOSTICS。
5.不支持对列GRANT INSERT/UPDATE权限。
6.不支持标准的CREATE TEMPORARY TABLE和LOCAL TEMPORARY TABLE,greenplum的临时表与Teradata的VOLATILE表同一个意思。
7.UNIQUE表述。
8.不支持MATCH PARTIAL
不支持SQL99的特性,包括:
1.不支持大数据对象CLOB、BLOB和NCLOB,但是其BYTEA和TEXT类型可以保存大数据类型。
2.不支持WITH的递归语句。
3.不支持MODULE。
4.没有CREATE PROCEDURE句法(SQL/PSM),可以用CREATE FUNCTION代替,返回void,用法如:select my_func(args);
5.greenplum/PostgreSQL的函数定义语言(PL/PGSQL)是Oracle的PL/SQL的子集,不兼容SQL/PSM语言;greenplum还支持用python、perl和R语言实现的函数定义。
6.特意不支持BIT、BIT VARYING类型,此类型在后来的SQL标准中已被取缔。
7.greenplum支持的标识符最长63字符,而SQL标准是128字符。
8.不支持prepared transaction。
9.CHARACTER SET option on the definition of CHAR() or VARCHAR() columns
——char和varchar类型对字符集有限制
10.不支持用字符或字节规定char()或varchar()列,比如VARCHAR(15 CHARACTERS) or VARCHAR(15 OCTETS) or VARCHAR(15 BYTES)
11.不支持CURRENT_SCHEMA??????(测试支持,select current_schema())
12.不支持CREATE DISTINCT TYPE语句,CREATE DOMAIN可以作为全能使用。
13.不支持表结构明细??????(测试\d 表名可以)
不支持SQL2003的特性,包括:
1.不支持XML类型,PostgreSQL支持。
2.不支持MERGE语句。
3.不支持IDENTITY列,以及GENERATED ALWAYS/GENERATED BY DEFAULT子句。
4.不支持数据类型的MULTISET修饰符。
5.不支持ROW数据类型。
6.Sequence用法不是标准的,比如nextval(‘seq’)是获取seq的下一个value。
7.不支持GENERATED ALWAYS AS列;可以用视图代替(views can be used as a work-around.)
8.在select的子句中不支持TABLESAMPLE;可以用random()代替。
9.在select和子句中不支持NULLS FIRST或NULLS LAST。
10.在表join时不支持PARTITION BY。
11.不支持对列进行grant select权限操作;可以用view实现。
12.对于CREATE TABLE X (LIKE Y)语句,不支持[INCLUDING|EXCLUDING] [DEFAULTS|CONSTRAINTS|INDEXES] 子句。
13.数组数据类型与SQL标准兼容但有例外,一般用户使用不会受影响。
不支持SQL2008的特性,包括:
1.不支持BINARY和VARBINARY类型,可以用BYTEA类型代替VARBINARY。
2.不支持FETCH FIRST、FETCH NEXT这样的句法,比如select * from sale order by id offset 20 rows fetch next 10 rows only;;可以用limit代替。
3.在VIEW和子查询中,ORDER BY最好与limit一起使用,否则会被忽略,因为可能会导致性能问题。
4.The row subquery construct is not supported.
5.TRUNCATE TABLE不支持CONTINUE IDENTITY和RESTART IDENTITY子句。
6.不支持CREATE FOREIGN DATA WRAPPER (SQL/MED)子句。
7.不支持CREATE SERVER(SQL/MED)子句。
8.不支持CREATE MAPPING(SQL/MED)子句。
----------------------------------------------------------------------------------------------------
greenplum的查询处理
查询计划器(query planner),意指在各个节点上分步骤的获取最后结果的过程,比如表扫描、join、聚集和排序操作。有的查询涉及到motion操作,即数据在segments之间迁移。对于一次查询任务,planner会把它切割成分片(slice),对应到各个segment上去,也就是说slice之间是独立的,但一个slice可能运行在多个segment上,比如一次motion操作肯定对应两边segment上的同一个slice任务。大多数的查询任务可能最后还要将segments上产生的结果通过gather motion操作发送到master上去展现给用户,记为一次slice;也有例外,比如CREATE TABLE X AS SELECT,没有gather motion操作,不需要将数据发送到master。
并行查询执行(parallel query execution),对于一次查询来说,首先master上建立查询分派进程(query dispatcher,QD),负责创建和分派query planner,以及收集和展现最终结果;在segment上的工作进程叫query executor(QE),负责完成自身任务以及和其他QE传输中间结果;对于每一个slice的执行,都是多进程作业的。query planner的每一个步骤叫做一个gangs,也就是说所有segments上的相同slice是一个gangs,gangs可能包含segments之间的数据流通信,再换句话说,一个并行查询执行,就是一个gangs接着一个gangs来完成的。
转载于:https://blog.51cto.com/jackwxh/1311339