使用GDS从远端服务器上导入表数据到DWS集群
教程指引
本教程旨在演示使用GDS工具将远端服务器上的数据导入DWS中的过程,帮助您学习如何通过GDS进行数据导入的方法。DWS支持通过GDS外表将TXT、CSV和FIXED格式的数据导入到集群进行查询。
GDS(General Data Service)是一款运行在Linux操作系统的命令行工具,通过和外表机制的配合,实现数据的高速导入导出。GDS工具包需要安装在数据源文件所在的服务器上,数据源文件所在的服务器称为数据服务器,也叫GDS服务器。
本教程仅用于测试环境演示,如果您在实际业务导入场景,应综合考虑GDS服务器与DWS集群之间的网络、GDS服务器配置等,参见了解更多:GDS导入数据调优实践。
在本教程中,您将:
- 生成本教程需要使用的CSV格式的数据源文件。
- 将数据源文件上传到数据服务器。
- 创建外表,用于对接GDS和DWS,将数据服务器上的数据导入到DWS集群中。
- 启动DWS并创建数据库表后,将数据导入到表中。
- 根据错误表中的提示诊断加载错误并更正这些错误。
视频介绍
准备ECS作为GDS服务器
购买Linux弹性云服务器的操作步骤,请参见《弹性云服务器快速入门》中的自定义购买弹性云服务器。购买后,请参见登录Linux弹性云服务器进行登录。

- ECS按以下最低规格配置。
- 生产环境下:网络:>=10GE网络;CPU:16U;内存:64G;存储:按需,建议不低于500GB。
- 测试环境下:网络:>=10GE网络;CPU:8U;内存:32G;存储:按需,建议不低于500GB。
- ECS操作系统必须是GDS工具包所支持的操作系统。
- ECS与DWS处于同一区域、同一虚拟私有云和子网。
- ECS安全组规则需放通DWS集群的访问,即安全组入规则:
- 协议:TCP
- 端口范围:5000
- 源地址:选择“IP地址”,输入DWS 集群地址,例如“192.168.0.10/32”。
- ECS内部如果启用了防火墙,需要保证防火墙打开了GDS服务的监听端口:
1
iptables -I INPUT -p tcp -m tcp --dport <gds_port> -j ACCEPT
下载GDS工具包
- 登录DWS控制台。
- 在左侧导航栏中,单击“管理 > 连接客户端”。
- 在“命令行客户端”的下拉列表中,选择对应版本的GDS客户端。
请根据集群版本和安装客户端的操作系统,选择对应版本。
客户端CPU架构要和集群一致,如果集群是X86规格,则也应该选择X86客户端。
- 单击“下载”。
准备数据源文件
- 数据文件“product_info0.csv”
1 2 3 4 5
100,XHDK-A,2017-09-01,A,2017 Shirt Women,red,M,328,2017-09-04,715,good! 205,KDKE-B,2017-09-01,A,2017 T-shirt Women,pink,L,584,2017-09-05,40,very good! 300,JODL-X,2017-09-01,A,2017 T-shirt men,red,XL,15,2017-09-03,502,Bad. 310,QQPX-R,2017-09-02,B,2017 jacket women,red,L,411,2017-09-05,436,It's nice. 150,ABEF-C,2017-09-03,B,2017 Jeans Women,blue,M,123,2017-09-06,120,good.
- 数据文件“product_info1.csv”
1 2 3 4 5
200,BCQP-E,2017-09-04,B,2017 casual pants men,black,L,997,2017-09-10,301,good quality. 250,EABE-D,2017-09-10,A,2017 dress women,black,S,841,2017-09-15,299,This dress fits well. 108,CDXK-F,2017-09-11,A,2017 dress women,red,M,85,2017-09-14,22,It's really amazing to buy. 450,MMCE-H,2017-09-11,A,2017 jacket women,white,M,114,2017-09-14,22,very good. 260,OCDA-G,2017-09-12,B,2017 woolen coat women,red,L,2004,2017-09-15,826,Very comfortable.
- 数据文件“product_info2.csv”
1 2 3 4 5 6 7 8 9 10
980,"ZKDS-J",2017-09-13,"B","2017 Women's Cotton Clothing","red","M",112,,, 98,"FKQB-I",2017-09-15,"B","2017 new shoes men","red","M",4345,2017-09-18,5473 50,"DMQY-K",2017-09-21,"A","2017 pants men","red","37",28,2017-09-25,58,"good","good","good" 80,"GKLW-l",2017-09-22,"A","2017 Jeans Men","red","39",58,2017-09-25,72,"Very comfortable." 30,"HWEC-L",2017-09-23,"A","2017 shoes women","red","M",403,2017-09-26,607,"good!" 40,"IQPD-M",2017-09-24,"B","2017 new pants Women","red","M",35,2017-09-27,52,"very good." 50,"LPEC-N",2017-09-25,"B","2017 dress Women","red","M",29,2017-09-28,47,"not good at all." 60,"NQAB-O",2017-09-26,"B","2017 jacket women","red","S",69,2017-09-29,70,"It's beautiful." 70,"HWNB-P",2017-09-27,"B","2017 jacket women","red","L",30,2017-09-30,55,"I like it so much" 80,"JKHU-Q",2017-09-29,"C","2017 T-shirt","red","M",90,2017-10-02,82,"very good."
- 新建文本文档并使用本地编辑工具(例如Visual Studio Code)打开后,将示例数据拷贝进文本文档中。
- 选择“格式 > 以UTF-8无BOM格式编码”。
- 选择“文件 > 另存为”。
- 在弹出的对话框中输入文件名后,将文件后缀设为.csv,单击“保存”。
- 以root用户登录GDS服务器。
- 创建数据文件存放目录“/input_data”。
1
mkdir -p /input_data
- 使用MobaXterm将数据源文件上传至上一步所创建的目录中。
安装并启动GDS
- 以root用户登录GDS服务器,创建存放GDS工具包的目录/opt/bin/dws。
1
mkdir -p /opt/bin/dws
- 将GDS工具包上传至上一步所创建的目录中。
以上传redhat版本的工具包为例 ,将GDS工具包“dws_client_8.1.x_redhat_x64.zip”上传至上一步所创建的目录中。
- 在工具包所在目录下,解压工具包。
1 2
cd /opt/bin/dws unzip dws_client_8.1.x_redhat_x64.zip
- 创建用户gds_user及其所属的用户组gdsgrp。此用户用于启动GDS,且需要拥有读取数据源文件目录的权限。
1 2
groupadd gdsgrp useradd -g gdsgrp gds_user
- 修改工具包以及数据源文件目录属主为创建的用户gds_user及其所属的用户组gdsgrp。
1 2
chown -R gds_user:gdsgrp /opt/bin/dws/gds chown -R gds_user:gdsgrp /input_data
- 切换到gds_user用户。
1
su - gds_user
若当前集群版本为8.0.x及之前低版本,请跳过7,直接执行8。
若当前集群版本为8.1.x及以上版本,则正常执行以下步骤。
- 执行环境依赖脚本。(仅8.1.x版本适用)
1 2
cd /opt/bin/dws/gds/bin source gds_env
- 启动GDS。
1
/opt/bin/dws/gds/bin/gds -d /input_data/ -p 192.168.0.90:5000 -H 10.10.0.1/24 -l /opt/bin/dws/gds/gds_log.txt -D
命令中的部分信息请根据实际填写。
- -d dir:保存有待导入数据的数据文件所在目录。本教程中为“/input_data/”。
- -p ip:port:GDS监听IP和监听端口。默认值为:127.0.0.1,需要替换为能跟DWS通信的万兆网IP。监听端口的取值范围:1024~65535。默认值为:8098。本教程配置为:192.168.0.90:5000。
- -H address_string:允许哪些主机连接和使用GDS服务。参数需为CIDR格式。此参数配置的目的是允许DWS集群可以访问GDS服务进行数据导入。所以请保证所配置的网段包含DWS集群各主机。
- -l log_file:存放GDS的日志文件路径及文件名。本教程为“/opt/bin/dws/gds/gds_log.txt”。
- -D:后台运行GDS。仅支持Linux操作系统下使用。
创建外表
- 使用SQL客户端工具连接DWS数据库。
- 创建如下外表:
LOCATION:请替换成实际的GDS地址和端口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
DROP FOREIGN TABLE IF EXISTS product_info_ext; CREATE FOREIGN TABLE product_info_ext ( product_price integer not null, product_id char(30) not null, product_time date , product_level char(10) , product_name varchar(200) , product_type1 varchar(20) , product_type2 char(10) , product_monthly_sales_cnt integer , product_comment_time date , product_comment_num integer , product_comment_content varchar(200) ) SERVER gsmpp_server OPTIONS( LOCATION 'gsfs://192.168.0.90:5000/*', FORMAT 'CSV' , DELIMITER ',', ENCODING 'utf8', HEADER 'false', FILL_MISSING_FIELDS 'true', IGNORE_EXTRA_DATA 'true' ) READ ONLY LOG INTO product_info_err PER NODE REJECT LIMIT 'unlimited';
返回如下信息表示创建成功:
1
CREATE FOREIGN TABLE
导入数据
- 使用如下语句在DWS中创建目标表product_info,用于存储导入的数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
DROP TABLE IF EXISTS product_info; CREATE TABLE product_info ( product_price integer not null, product_id char(30) not null, product_time date , product_level char(10) , product_name varchar(200) , product_type1 varchar(20) , product_type2 char(10) , product_monthly_sales_cnt integer , product_comment_time date , product_comment_num integer , product_comment_content varchar(200) ) WITH ( orientation = column, compression=middle ) DISTRIBUTE BY hash (product_id);
- 将数据源文件中的数据通过外表“product_info_ext”导入到表“product_info”中。
1
INSERT INTO product_info SELECT * FROM product_info_ext ;
返回如下信息,表示数据导入成功。1
INSERT 0 20
- 执行SELECT命令查询目标表product_info,查看导入到DWS中的数据。
1
SELECT count(*) FROM product_info;
查询结果显示结果如下,表示导入成功。
1 2 3 4
count ------- 20 (1 row)
- 对表product_info执行VACUUM FULL。
1
VACUUM FULL product_info
- 更新表product_info的统计信息。
1
ANALYZE product_info;
停止GDS
- 以gds_user用户登录安装GDS的数据服务器。
- 使用以下方式停止GDS。
- 执行如下命令,查询GDS进程号。其中,GDS进程号为128954。
ps -ef|grep gds gds_user 128954 1 0 15:03 ? 00:00:00 gds -d /input_data/ -p 192.168.0.90:5000 -l /opt/bin/gds/gds_log.txt -D gds_user 129003 118723 0 15:04 pts/0 00:00:00 grep gds
- 使用“kill”命令,停止GDS。其中,128954为上一步骤中查询出的GDS进程号。
kill -9 128954
- 执行如下命令,查询GDS进程号。其中,GDS进程号为128954。
清除资源
- 执行以下命令,删除目标表product_info。
1
DROP TABLE product_info;
当结果显示为如下信息,表示删除成功。
1
DROP TABLE
- 执行以下命令,删除外表product_info_ext。
1
DROP FOREIGN TABLE product_info_ext;
当结果显示为如下信息,表示删除成功。
1
DROP FOREIGN TABLE
了解更多:GDS导入数据调优实践
- 安装GDS前必须确认GDS所在服务器环境的系统参数是否和数据库集群的系统参数一致。
- GDS如果部署在弹性云服务器ECS上,ECS按以下最低规格配置。
- 生产环境下:网络:>=10GE网络;CPU:16U;内存:64G;存储:按需,建议不低于500GB。
- 测试环境下:网络:>=10GE网络;CPU:8U;内存:32G;存储:按需,建议不低于500GB。
- GDS与DWS通信要求物理网络畅通,尽量使用万兆网(10GE网络)。因为千兆网无法承载高速的数据传输压力,极易出现断连,使用千兆网时DWS无法提供通信保障。满足万兆网的同时,要求数据磁盘组I/O性能大于GDS单核处理能力上限(约400MB/s),才能保证单文件导入速率最大化。
- 提前做好服务部署规划,数据服务器上,建议一个Raid只布1~2个GDS。GDS跟DN的数据比例建议在1:3至1:6之间。一台加载机的GDS进程不宜部署太多,千兆网卡部署1个GDS进程即可,万兆网卡机器建议部署不大于4个进程。
- 提前对GDS导入导出的数据目录做好层次划分,避免一个数据目录包含过多的文件,并及时清理过期文件。
- 合理规划目标数据库的字符集,强烈建议使用UTF8作为数据库的字符集,不建议使用sql_ascii编码,因为极易引起混合编码问题。GDS导出时保证外表的字符集和客户端字符集一致即可,导入时保证客户端编码,数据文件内容编码和客户端一致。
- 如果存在无法变更数据库,客户端,外表字符集时,可以尝试使用iconv命令进行手动转换。
1 2
#注意 -f 表示源文件的字符集,-t为目标字符集 iconv -f utf8 -t gbk utf8.txt -o gbk.txt
-
关于GDS导入实践可参考使用GDS导入数据。
-
GDS支持CSV、TEXT、FIXED三种格式,缺省为TEXT格式。不支持二进制格式,但是可以使用encode/decode函数处理二进制类型。例如:
对二进制表导出:1 2 3 4 5 6 7 8 9 10 11 12
--创建表。 CREATE TABLE blob_type_t1 ( BT_COL BYTEA ) DISTRIBUTE BY REPLICATION; -- 创建外表 CREATE FOREIGN TABLE f_blob_type_t1( BT_COL text ) SERVER gsmpp_server OPTIONS (LOCATION 'gsfs://127.0.0.1:7789/', FORMAT 'text', DELIMITER E'\x08', NULL '', EOL '0x0a' ) WRITE ONLY; INSERT INTO blob_type_t1 VALUES(E'\\xDEADBEEF'); INSERT INTO blob_type_t1 VALUES(E'\\xDEADBEEF'); INSERT INTO blob_type_t1 VALUES(E'\\xDEADBEEF'); INSERT INTO blob_type_t1 VALUES(E'\\xDEADBEEF'); INSERT INTO f_blob_type_t1 select encode(BT_COL,'base64') from blob_type_t1;
对二进制表导入:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
--创建表。 CREATE TABLE blob_type_t2 ( BT_COL BYTEA ) DISTRIBUTE BY REPLICATION; -- 创建外表 CREATE FOREIGN TABLE f_blob_type_t2( BT_COL text ) SERVER gsmpp_server OPTIONS (LOCATION 'gsfs://127.0.0.1:7789/f_blob_type_t1.dat.0', FORMAT 'text', DELIMITER E'\x08', NULL '', EOL '0x0a' ); insert into blob_type_t2 select decode(BT_COL,'base64') from f_blob_type_t2; SELECT * FROM blob_type_t2; bt_col ------------ \xdeadbeef \xdeadbeef \xdeadbeef \xdeadbeef (4 rows)
-
若不确定文件是否为标准的csv格式,推荐将quote参数设置为0x07,0x08或0x1b等不可见字符来进行GDS导入导出,避免文件格式问题导致任务失败。
1 2 3 4 5
CREATE FOREIGN TABLE foreign_HR_staffS_ft1 ( MANAGER_ID NUMBER(6), section_ID NUMBER(4) ) SERVER gsmpp_server OPTIONS (location 'file:///input_data/*', format 'csv', mode 'private', quote '0x07', delimiter ',') WITH err_HR_staffS_ft1;
-
GDS支持并发导入导出,gds -t参数用于设置gds的工作线程池大小,控制并发场景下同时工作的工作线程数且不会加速单个sql任务。gds -t缺省值为8,上限值为200。在使用管道功能进行导入导出时,-t参数应不低于业务并发数。
- GDS外表参数delimiter是多字符时,建议TEXT格式下字符不要完全相同。例如,不建议使用delimiter '---'。
- GDS多表并行导入同一个文件提升导入性能(仅支持text和csv文件)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
-- 创建目标表。 CREATE TABLE pipegds_widetb_1 (city integer, tel_num varchar(16), card_code varchar(15), phone_code varchar(16), region_code varchar(6), station_id varchar(10), tmsi varchar(20), rec_date integer(6), rec_time integer(6), rec_type numeric(2), switch_id varchar(15), attach_city varchar(6), opc varchar(20), dpc varchar(20)); -- 创建带有file_sequence字段的外表。 CREATE FOREIGN TABLE gds_pip_csv_r_1( like pipegds_widetb_1) SERVER gsmpp_server OPTIONS (LOCATION 'gsfs://127.0.0.1:8781/wide_tb.txt', FORMAT 'text', DELIMITER E'|+|', NULL '', file_sequence '5-1'); CREATE FOREIGN TABLE gds_pip_csv_r_2( like pipegds_widetb_1) SERVER gsmpp_server OPTIONS (LOCATION 'gsfs://127.0.0.1:8781/wide_tb.txt', FORMAT 'text', DELIMITER E'|+|', NULL '', file_sequence '5-2'); CREATE FOREIGN TABLE gds_pip_csv_r_3( like pipegds_widetb_1) SERVER gsmpp_server OPTIONS (LOCATION 'gsfs://127.0.0.1:8781/wide_tb.txt', FORMAT 'text', DELIMITER E'|+|', NULL '', file_sequence '5-3'); CREATE FOREIGN TABLE gds_pip_csv_r_4( like pipegds_widetb_1) SERVER gsmpp_server OPTIONS (LOCATION 'gsfs://127.0.0.1:8781/wide_tb.txt', FORMAT 'text', DELIMITER E'|+|', NULL '', file_sequence '5-4'); CREATE FOREIGN TABLE gds_pip_csv_r_5( like pipegds_widetb_1) SERVER gsmpp_server OPTIONS (LOCATION 'gsfs://127.0.0.1:8781/wide_tb.txt', FORMAT 'text', DELIMITER E'|+|', NULL '', file_sequence '5-5'); --将wide_tb.txt并发导入到pipegds_widetb_1。 \parallel on INSERT INTO pipegds_widetb_1 SELECT * FROM gds_pip_csv_r_1; INSERT INTO pipegds_widetb_1 SELECT * FROM gds_pip_csv_r_2; INSERT INTO pipegds_widetb_1 SELECT * FROM gds_pip_csv_r_3; INSERT INTO pipegds_widetb_1 SELECT * FROM gds_pip_csv_r_4; INSERT INTO pipegds_widetb_1 SELECT * FROM gds_pip_csv_r_5; \parallel off
file_sequence参数详细内容,可参考CREATE FOREIGN TABLE (GDS导入导出)章节。