开发者社区> 问答> 正文

如何使用 OSS 外部表同步数据

云数据库 HybridDB for PostgreSQL 支持通过 OSS 外部表(即 gpossext 功能),将数据并行从 OSS 导入或导出到 OSS,并支持通过 gzip 进行 OSS 外部表文件压缩,大量节省存储空间及成本。
本文内容包括:


[backcolor=transparent]

操作说明


通过 HybridDB for PostgreSQL 使用 OSS 外部表,主要涉及以下操作。
[backcolor=transparent]

创建 OSS 外部表插件(oss_ext)


使用 OSS 外部表时,需要在 HybridDB for PostgreSQL 中先创建 OSS 外部表插件(每个数据库需要单独创建)。
  • 创建命令为:CREATE EXTENSION IF NOT EXISTS oss_ext;
  • 删除命令为:DROP EXTENSION IF EXISTS oss_ext;

[backcolor=transparent]

并行导入数据


导入数据时,请执行如下步骤:

  1. 将数据均匀分散存储在多个 OSS 文件中,文件的数目最好为 HybridDB for PostgreSQL 数据节点数(Segment 个数)的整数倍。

  2. 在 HybridDB for PostgreSQL 中,创建 READABLE 外部表。

  3. 执行如下操作,并行导入数据。
    INSERT INTO <目标表> SELECT * FROM <外部表>

[backcolor=transparent]

并行导出数据


导出数据时,请执行如下步骤:

  1. 在 HybridDB for PostgreSQL 中,创建 WRITABLE 外部表。

  2. 执行如下操作,并行把数据导出到 OSS 中。
    INSERT INTO <外部表> SELECT * FROM <源表>

[backcolor=transparent]

创建 OSS 外部表语法


创建 OSS 外部表语法,请执行如下命令: CREATE [READABLE] EXTERNAL TABLE tablename
( columnname datatype [, ...] | LIKE othertable )
LOCATION ('ossprotocol')
FORMAT 'TEXT'
            [( [HEADER]
               [DELIMITER [AS] 'delimiter' | 'OFF']
               [NULL [AS] 'null string']
               [ESCAPE [AS] 'escape' | 'OFF']
               [NEWLINE [ AS ] 'LF' | 'CR' | 'CRLF']
               [FILL MISSING FIELDS] )]
           | 'CSV'
            [( [HEADER]
               [QUOTE [AS] 'quote']
               [DELIMITER [AS] 'delimiter']
               [NULL [AS] 'null string']
               [FORCE NOT NULL column [, ...]]
               [ESCAPE [AS] 'escape']
               [NEWLINE [ AS ] 'LF' | 'CR' | 'CRLF']
               [FILL MISSING FIELDS] )]
[ ENCODING 'encoding' ]
[ [LOG ERRORS [INTO error_table]] SEGMENT REJECT LIMIT count
       [ROWS | PERCENT] ]
CREATE WRITABLE EXTERNAL TABLE table_name
( column_name data_type [, ...] | LIKE other_table )
LOCATION ('ossprotocol')
FORMAT 'TEXT'
               [( [DELIMITER [AS] 'delimiter']
               [NULL [AS] 'null string']
               [ESCAPE [AS] 'escape' | 'OFF'] )]
          | 'CSV'
               [([QUOTE [AS] 'quote']
               [DELIMITER [AS] 'delimiter']
               [NULL [AS] 'null string']
               [FORCE QUOTE column [, ...]] ]
               [ESCAPE [AS] 'escape'] )]
[ ENCODING 'encoding' ]
[ DISTRIBUTED BY (column, [ ... ] ) | DISTRIBUTED RANDOMLY ]
ossprotocol:
   oss://oss_endpoint prefix=prefix_name
    id=userossid key=userosskey bucket=ossbucket compressiontype=[none|gzip] async=[true|false]
ossprotocol:
   oss://oss_endpoint dir=[folder/[folder/]...]/file_name
    id=userossid key=userosskey bucket=ossbucket compressiontype=[none|gzip] async=[true|false]
ossprotocol:
   oss://oss_endpoint filepath=[folder/[folder/]...]/file_name
    id=userossid key=userosskey bucket=ossbucket compressiontype=[none|gzip] async=[true|false]


[backcolor=transparent]

参数释义


该部分介绍各操作中用到的参数定义,涉及到参数包括:
[backcolor=transparent]

常用参数


  • 协议和 endpoint:格式为“协议名://oss_endpoint”,协议名为 oss,oss_endpoint 为 OSS 对应区域的域名。

    [backcolor=transparent]注意:如果是从阿里云的主机访问,应该使用内网域名(即带有“internal”的域名),避免产生公网流量。

  • id:OSS 账号的 ID。

  • key:OSS 账号的 key。

  • bucket:指定数据文件所在的 bucket,需要通过 OSS 预先创建。

  • prefix:指定数据文件对应路径名的前缀,不支持正则表达式,仅是匹配前缀,且与 filepath、dir 互斥,不能同时指定。
    如果创建的是用于数据导入的 READABLE 外部表,则在导入时含有这一前缀的所有 OSS 文件都会被导入。如果指定 prefix=test/filename,以下文件都会被导入:test/filename
  • test/filenamexxx
  • test/filename/aa
  • test/filenameyyy/aa
  • test/filenameyyy/bb/aa
如果指定 prefix=test/filename/,只有以下文件会被导入(上面列的其他文件不会被导入):
  • test/filename/aa

如果创建的是用于数据导出的 WRITABLE 外部表,在导出数据时,将根据该前缀自动生成一个唯一的文件名来给导出文件命名。

[backcolor=transparent]注意:导出文件将不止有一个,每个数据节点都会导出一个或多个文件。导出文件名格式为 prefix_tablename_uuid.x,其中 uuid 是生成的 int64 整型值(微秒时间戳),x 为节点 ID。支持使用同一外部表多次导出,每次导出的文件将通过 uuid 区分,而同一次导出的文件 uuid 相同。

dir:OSS 中的虚拟文件夹路径,与 prefix、filepath 互斥。
  • 文件夹路径需要以“/”结尾,如test/mydir/。
  • 在导入数据时,使用此参数创建外部表,会导入指定虚拟目录下的所有文件,但不包括它子目录和子目录下的文件。与 filepath 不同,dir 下的文件没有命名要求。
  • 在导出数据时,使用此参数创建外部表,所有数据会导出到此目录下的多个文件中,输出文件名的形式为filename.x,x 为数字,但可能不是连续的。

filepath:OSS 中带路径的文件名,与 prefix、dir 互斥,且只能在创建 READABLE 外部表时指定(即只支持在导入数据时使用)。
  • 文件名包含文件路径,但不包含 bucket 名。
  • 在导入数据时,文件命名方式必须为 filename 或 filename.x,x 要求从 1 开始,且是连续的。例如,如果指定 filepath = filename,而 OSS 中含有如下文件:filename
  • filename.1
  • filename.2
  • filename.4,


  • 则将被导入的文件有 filename、filename.1 和 filename.2,而因为 filename.3 不存在,filename.4 不会被导入。

[backcolor=transparent]

导入模式参数


  • async:是否启用异步模式装载数据。
    开启辅助线程从 OSS 装载数据,加速导入性能,默认导入模式是异步模式。

  • 默认情况下异步模式是打开的,如果需要关掉,可以使用参数 async = false 或 async = f。

  • 异步模式和普通模式比,会消耗更多的硬件资源。

compressiontype:导入的文件的压缩格式。

  • 指定为 none(缺省值),说明导入的文件没经过压缩。

  • 指定为 gzip,则导入的格式为 gzip。目前仅支持 gzip 压缩格式。

[backcolor=transparent]

导出模式参数


  • oss_flush_block_size:单次刷出数据到 OSS 的 buffer 大小,默认为 32 MB,可选范围是 1 到 128 MB。

  • oss_file_max_size: 写到 OSS 的最大文件大小,超出之后会切换到另一个文件继续写。默认为 1024 MB,可选范围是 8 到 4000 MB。

另外,针对导出模式,需要注意如下事项:

  • WRITABLE 是导出模式外部表的关键字,创建外部表时需要明确指明。

  • 导出模式目前只支持 prefix 和 dir 参数模式,不支持 filepath。

  • 导出模式的 DISTRIBUTED BY 子句可以使数据节点(Segment)按指定的分布键将数据写入 OSS。

[backcolor=transparent]

其他通用参数


针对导入模式和导出模式,还有下列容错相关参数:

  • oss_connect_timeout:设置链接超时,单位秒,默认是 10 秒。

  • oss_dns_cache_timeout:设置 DNS 超时,单位秒,默认是 60 秒。

  • oss_speed_limit:控制能容忍的最小速率,默认是 1024,即 1 K。

  • oss_speed_time:控制能容忍的最长时间,默认是 15 秒。

上述参数如果使用默认值,则如果连续 15 秒的传输速率小于 1 K,就会触发超时。详细描述请参见 OSS SDK 错误处理
其他参数兼容 Greenplum EXTERNAL TABLE 的原有语法,具体语法解释请参见 Greenplum 外部表语法官方文档。这部分参数主要有:

  • FORMAT:支持文件格式,支持 text、csv 等。

  • ENCODING:文件中数据的编码格式,如 utf8。

  • LOG ERRORS:指定该子句可以忽略掉导入中出错的数据,将这些数据写入error_table,并可以使用count参数指定报错的阈值。

[backcolor=transparent]

使用示例#  创建 OSS 导入外部表
create readable external table ossexample
        (date text, time text, open float, high float,
        low float, volume int)
        location('oss://oss-cn-hangzhou.aliyuncs.com
        prefix=osstest/example id=XXX
        key=XXX bucket=testbucket compressiontype=gzip')
        FORMAT 'csv' (QUOTE '''' DELIMITER E'\t')
        ENCODING 'utf8'
        LOG ERRORS INTO my_error_rows SEGMENT REJECT LIMIT 5;
create readable external table ossexample
        (date text, time text, open float, high float,
        low float, volume int)
        location('oss://oss-cn-hangzhou.aliyuncs.com
        dir=osstest/ id=XXX
        key=XXX bucket=testbucket')
        FORMAT 'csv'
        LOG ERRORS SEGMENT REJECT LIMIT 5;
create readable external table ossexample
        (date text, time text, open float, high float,
        low float, volume int)
        location('oss://oss-cn-hangzhou.aliyuncs.com
        filepath=osstest/example.csv id=XXX
        key=XXX bucket=testbucket')
        FORMAT 'csv'
        LOG ERRORS SEGMENT REJECT LIMIT 5;
# 创建 OSS 导出外部表
create WRITABLE external table ossexample_exp
        (date text, time text, open float, high float,
        low float, volume int)
        location('oss://oss-cn-hangzhou.aliyuncs.com
        prefix=osstest/exp/outfromhdb id=XXX
        key=XXX bucket=testbucket') FORMAT 'csv'
        DISTRIBUTED BY (date);
create WRITABLE external table ossexample_exp
        (date text, time text, open float, high float,
        low float, volume int)
        location('oss://oss-cn-hangzhou.aliyuncs.com
        dir=osstest/exp/ id=XXX
        key=XXX bucket=testbucket') FORMAT 'csv'
        DISTRIBUTED BY (date);
# 创建堆表,数据就装载到这张表中
create table example
        (date text, time text, open float,
         high float, low float, volume int)
         DISTRIBUTED BY (date);
# 数据并行的从 ossexample 装载到 example 中
insert into example select * from ossexample;
# 数据并行的从 example 导出到 oss
insert into ossexample_exp select * from example;
# 从下面的执行计划中可以看出,每个 Segment 都会参与工作。
# 每个 Segment 从 OSS 并行拉取数据,然后通过 Redistribution Motion 这个执行节点将拿到的数据 HASH 计算后分发给对应的 Segment,接受数据的 Segment 通过 Insert 执行节点进行入库。
explain insert into example select * from ossexample;
                                            QUERY PLAN                                            
-----------------------------------------------------------------------------------------------
Insert (slice0; segments: 4)  (rows=250000 width=92)
   ->  Redistribute Motion 4:4  (slice1; segments: 4)  (cost=0.00..11000.00 rows=250000 width=92)
         Hash Key: ossexample.date
         ->  External Scan on ossexample  (cost=0.00..11000.00 rows=250000 width=92)
(4 rows)
# 从下面的查询计划可以看到,Segment 把本地数据直接导出到 OSS ,没有进行数据重分布
explain insert into ossexample_exp select * from example;
                          QUERY PLAN                          
---------------------------------------------------------------
Insert (slice0; segments: 3)  (rows=1 width=92)
   ->  Seq Scan on example  (cost=0.00..0.00 rows=1 width=92)
(2 rows)




[backcolor=transparent]

注意事项


  • 创建和使用外部表的语法,除了 location 相关的参数,其余部分和 Greenplum 相同。

  • 数据导入的性能和 HybridDB for PostgreSQL 集群的资源(CPU、IO、内存、网络等)相关,也和 OSS 相关。为了获取最大的导入性能,建议在创建表时,使用列式存储 + 压缩功能。例如,指定子句“WITH (APPENDONLY=true, ORIENTATION=column, COMPRESSTYPE=zlib, COMPRESSLEVEL=5, BLOCKSIZE=1048576)”,详情请参见 Greenplum Database 表创建语法官方文档

  • 为保证数据导入的性能,ossendpoint Region 需要匹配 HybridDB for PostgreSQL 云上所在 Region,建议 OSS 和 HybridDB for PostgreSQL 在同一个 Region 内以获得最好的性能。相关信息请参见 OSS endpoint 信息

[backcolor=transparent]

TEXT/CSV 格式说明


下列几个参数可以在外表 DDL 参数中指定,用于规定读写 OSS 上的文件格式
  • TEXT/CSV 行分割符号是 ‘\n’ ,也就是换行符
  • DELIMITER 用于定义列的分割符当用户数据中包括 DELIMITER 时,则需要配合 QUOTE 参数。
  • 推荐的列分割符有 ‘,’、‘\t‘ 、‘|’ 或一些不常出现的字符。
QUOTE 以列为单位包裹有特殊字符的用户数据
  • 用户包含有特殊字符的字符串会被 QUOTE 包裹,用于区分用户数据和控制字符。
  • 如果不必要,例如整数,数据不会被 QUOTE 包裹(用于优化效率)。
  • QUOTE 不能和 DELIMITER 相同,默认 QUOTE 是双引号。
  • 当用户数据中包含了 QUOTE 字符,则需要使用转义字符 ESCAPE 加以区分。
ESCAPE 特殊字符转义
  • 转义字符出现在需要转义的特殊字符前,表示它不是一个特殊字符
  • ESCAPE 默认和 QUOTE 相同,也就是双引号。
  • 也支持设置成 ‘\’(MySQL 默认的转义字符)或别的字符。


典型的 TEXT/CSV 默认控制字符

控制字符 \ 格式TEXTCSV
DELIMITER(列分割符)\t (tab), (comma)
QUOTE(摘引)“ (double-quote)“(double-quote)
ESCAPE(转义)(不适用)和 QUOTE 相同
NULL(空值)\N (backslash-N)(无引号的空字符串)

所有的控制字符都必须是单字节字符更多信息参考:
[backcolor=transparent]

SDK 错误处理


当导入或导出操作出错时,错误日志可能会出现如下信息:

  • code:出错请求的 HTTP 状态码。

  • error_code:OSS 的错误码。

  • error_msg:OSS 的错误信息。

  • req_id:标识该次请求的 UUID。当您无法解决问题时,可以凭 req_id 来请求 OSS 开发工程师的帮助。

详情请参见 OSS API 错误响应,超时相关的错误可以使用 oss_ext 相关参数处理。
[backcolor=transparent]

常见问题


导入过慢。请参见上面“注意事项”中关于导入性能的描述。

展开
收起
云栖大讲堂 2017-11-01 10:40:44 2804 0
0 条回答
写回答
取消 提交回答
问答排行榜
最热
最新

相关电子书

更多
OSS运维进阶实战手册 立即下载
《OSS运维基础实战手册》 立即下载
OSS运维基础实战手册 立即下载