本文章介绍Greenplum(简称GP)的并行化数据加载。

GP数据库使用外部表特性支持快速,并行化的数据加载。我们可以使用单行错误隔离模式来加载外部表数据,将错误或格式有问题的记录数加载到独立的错误表里面。

通过使用外部表结合GP数据库的并行文件服务器gpfdist功能,我们能够实现最大并行度和加载带宽。

如下图使用gpfdist实现外部表数据加载:

 

greenplum6 系统表说明 greenplum gpload_控制文件

Greenplum数据库另外也提供gpload工具用来进行数据装载的工具,我们既可以在服务端访问它,也可以把它拷贝到远程的ETL服务器,进行远程数据加载。

Greenplum的gpload工具通过可读外部表和并行化文件服务器gpfdist(或gpfdists)来加载数据。gpload处理并行化的基于文件的外部表设置,以及允许我们使用单个YAML文件来配置数据格式,外部表定义,以及gpfdist或gpfdists。

要使用gpload工具有几个前提条件必须满足:

1.

使用gpload的服务器必须安装Python 2.6.2或者以上版本,pygresql工具和pyyaml工具(数据库服务端已经安装了python和需要的python库文件)

2.

必须装gpfdist程序,并把它设置到环境变量PATH中(可以从数据库服务器端的安装目录的子目录bin中拷贝该工具)

3.

确保使用gpload工具的ETL服务器与Greenplum所有服务器的联通性,以及机器名解析正确

gpload通过它的控制文件(YAML格式控制文件)指定装载的细节信息。所以编写控制文件是用好gpload的关键所在。gpload的控制文件采用YAML1.0.0.1文档格式编写,因此它必须得是有效的YAML格式。

下面我们先举个yaml格式的例子:

1.

先创建序列,用来作为记录gpload的审计记录的ID

--创建序列 
create SEQUENCE gpload_audit_seq INCREMENT BY 1 MINVALUE 1 NO MAXVALUE START WITH 1; 
select * from gpload_audit_seq ; 
--创建审计表,记录每一次gpload执行的开始和结束事件信息 
create table gpload_audit( 
    id bigint, 
    state text, 
    mode text, 
    tablename text, 
    updatetime timestamp 
) distributed by (id);

2.

创建gpload加载数据的表

CREATE TABLE expenses 
( 
    name text, 
    amount numeric, 
    category text, 
    des text, 
    update_date date 
);

3.

编写gpload需要的yaml格式的文件my_load.yml,内容如下:

--- 
VERSION: 1.0.0.1 
DATABASE: zhangyun_db 
USER: zhangyun 
HOST: cdha 
PORT: 5432 
GPLOAD: 
    INPUT: 
        - SOURCE: 
            LOCAL_HOSTNAME: 
                - cdha 
            PORT: 8081 
            FILE: 
                - /var/gpload/data 
        - COLUMNS: 
            - name: text 
            - amount: float4 
            - category: text 
            - des: text 
            - update_date: date 
        - FORMAT: text 
        - DELIMITER: '|' 
        - ERROR_LIMIT: 25 
        - ERROR_TABLE: zhangyun_schema.expenses_err 
    OUTPUT: 
        - TABLE: zhangyun_schema.expenses 
        - MODE: INSERT 
    PRELOAD: 
        - TRUNCATE: true 
    SQL: 
        - BEFORE: "INSERT INTO gpload_audit VALUES(nextval('gpload_audit_seq'), 'start', 'insert', 'zhangyun_schema.expenses', current_timestamp)" 
        - AFTER: "INSERT INTO gpload_audit VALUES(nextval('gpload_audit_seq'), 'end', 'insert', 'zhangyun_schema.expenses', current_timestamp)"

  

4.

执行gpload转载数据

gpload -f my_load.yml

5.

验证表

--查看数据表

zhangyun_db=# select * from expenses; 
 name  | amount | category | des  | update_date  
-------+--------+----------+------+------------- 
 Spark |    100 | high     | 专家 | 2016-06-06 
(1 row) 
--查看审计表 
zhangyun_db=# select * from gpload_audit; 
 id | state |  mode  |        tablename         |         updatetime          
----+-------+--------+--------------------------+---------------------------- 
 1 | start | insert | zhangyun_schema.expenses | 2016-07-03 22:14:08.376522 
 2 | end  | insert | zhangyun_schema.expenses | 2016-07-03 22:14:09.589961

最后将yaml里面的配置说明一下:

---

VERSION: 1.0.0.1            --指定控制文件schema的版本

DATABASE: db_name           --指定连接数据库的名字,如果没有指定,由环境变量$PGDATABASE,或者通过gpload参数-d指定

USER: db_username           --指定连接目标数据库的用户名,如果不使用超级管理员,服务参数gp_external_grant_privileges必须设置成on

HOST: master_hostname       --指定master主机名,也可以通过gpload的-h选项,或者环境变量$PGHOST指定

PORT: master_port           --指定master的连接端口号,默认是5432,或者通过gpload命令的-p选项或者环境变量$PGPORT指定。

GPLOAD:                     --必须指定,表示装载设置部分在它下面必须定义INPUT:和OUTPUT:两个部分。

   

INPUT:                      --必须指定,这部分指定装载数据的格式和位置

        -

SOURCE:                   --必须指定,定义source文件的位置,每个输入部分可以定义多个source部分

           

LOCAL_HOSTNAME:             --指定gpload运行的主机名称和ip地址,如果有多块网卡,可以同时使用它们,提高装载速度。默认只使用首选主机名和IP

                - hostname_or_ip

           

PORT: http_port             --指定gpfdist使用的端口,也可以选择端口范围,由系统选择,如果同时指定,port设置优先级高

            |

PORT_RANGE: [start_port_range, end_port_range]

           

FILE:                       --指定装载数据文件的位置,目录或者命名管道。如果文件使用gpzip或者bzip2进行了压缩,它可以自动解压。可以使用通配符*和C语言风格的关系匹配模式指定多个文件

                - /path/to/input_file

        -

COLUMNS:                    --指定数据源的数据格式,如果没有指定这部分,source表的列顺序,数量,以及数据类型必须与目标表一致

            - field_name: data_type

        -

FORMAT: text | csv          --指定文件格式是text还是csv

        -

DELIMITER: 'delimiter_character'  --指定文本数据域(列)之间的分割符,默认是|

        -

ESCAPE: 'escape_character' | 'OFF'  --text定义转义字符,text格式默认是\,在text格式中可以选择off关掉转义字符

        -

NULL_AS: 'null_string'       --指定描述空值的字符串,text格式默认是\N,csv格式不使用转义符号的空值

        -

FORCE_NOT_NULL: true | false --csv格式,强制所有字符默认都用”“括起,因此不能有空值,如果两个分割符之间没有值,被当做0长度字符串,认为值已经丢失

        -

QUOTE: 'csv_quote_character'  --csv指定转义字符,默认是"

        -

HEADER: true | false          --是否跳过数据文件第一行,当做表头

        -

ENCODING: database_encoding   --指定数据源的字符集

        -

ERROR_LIMIT: integer          --指定由于不符合格式数据记录的上限,如果超过该上限,gpload停止装载,否则正确记录可以被装载,错误记录抛出写入错误表。但它仅支持数据格式错误,不支持违背约束的问题

        -

ERROR_TABLE: schema.table_name --指定不符合格式要求记录的错误表。如果指定的表不存在系统自动创建

   

OUTPUT:

        -

TABLE: schema.table_name       --指定装载的目标表

        -

MODE: insert | update | merge  --指定操作模式,默认是insert。merge操作不支持使用随机分布策略的表

        -

MATCH_COLUMNS:                 --为update操作和merge操作指定匹配条件。

            - target_column_name            

        -

UPDATE_COLUMNS:                 --为update操作和merge操作指定更新的列

            - target_column_name

        -

UPDATE_CONDITION: 'boolean_condition'  --指定where条件,目标表中只有满足条件的记录才能更改,(merge情况下,只有满足条件的记录才能insert)

        -

MAPPING:                        --指定source列和目标列的映射关系。

            target_column_name: source_column_name | 'expression'

   

PRELOAD:                          --指定load之前的操作

        -

TRUNCATE: true | false          --如果设置成true,装载之前先删除目标表中所有记录,再装载

        -

REUSE_TABLES: true | false     --设置成true,不会删除外部表对象或者中间表对象。从而提升性能。

   

SQL:

        -

BEFORE: "sql_command"         --装载操作开始前执行的SQL,比如写日志表

        -

AFTER: "sql_command"          --装载操作之后执行的SQL