
# 使用gs_loader工具导入数据
#### 操作场景
对于copy to导出的文件，可以使用gs_loader工具进行数据导入。gs_loader将控制文件支持的语法转换为\\COPY语法，然后利用已有的\\COPY功能，做主要数据导入工作，同时gs_loader将\\COPY结果记录到日志中。
#### 注意事项
- gs_loader工具当前不支持M-Compatibility数据库。
- 使用gs_loader前请确保gs_loader版本与gsql版本、数据库版本保持一致。
- gs_loader当前仅支持集中式版。
- gs_loader导入过程中，不需要转码场景下，单行数据（包含tuple的元数据，以下均包含）小于1GB-1B；转码场景下单行数据小于256MB-1B，对以下转码场景进行了特殊处理：UTF-8 -\> GB18030/GB18030_2022的限制为小于512MB-1B，UTF-8 -\> GBK的限制为小于1GB-1B。
- 建议单个导入文件的大小不超过1GB。gs_loader对单个导入文件的大小没有限制，但是对大文件数据的导入通常会比较耗时，因此建议在使用的过程中，对较大的数据文件进行切分，启动多个gs_loader进程以append的形式向表中写入数据（如果有truncate的需要则需要单独执行truncate，而不是将truncate写入控制文件中）。在CPU资源足够时，这种做法可以有效地提升导入速率。
 
#### 迁移准备
1. 准备弹性云服务器或可通过公网访问GaussDB。
   - 通过弹性云服务器连接GaussDB数据库实例，需要创建一台弹性云服务器。 创建并登录弹性云服务器，详细内容请参见"[购买弹性云服务器](https://support.huaweicloud.com/usermanual-ecs/ecs_03_7002.html)"和"[登录弹性云服务器](https://support.huaweicloud.com/ecs_faq/ecs_faq_0632.html)"。
     
   
   - 通过公网地址连接GaussDB数据库实例，需具备以下条件。
     1. 先对GaussDB数据库实例绑定公网地址，如何绑定公网地址，请参见[绑定弹性公网IP](https://support.huaweicloud.com/usermanual-gaussdb/gaussdb_01_160.html)。
     
     2. 保证本地设备可以访问GaussDB数据库实例绑定的公网地址。
      
    
2. 在准备的弹性云服务器或可访问GaussDB数据库的设备上，安装gsql客户端，并连接到GaussDB数据库实例。详情请参见[使用gsql连接数据库](https://support.huaweicloud.com/usermanual-gaussdb/gaussdb_01_503.html#ZH-CN_TOPIC_0000002649773052__li107091547192)。
 
#### 操作步骤
1. 创建控制文件，准备数据文件。 
   1. 创建控制文件，将数据导入到loader_tbl表中，如'/tmp/data/loader.ctl'。其中WHEN要求每行第二个字符为','。
      ```
      LOAD DATA
      truncate into table loader_tbl
      WHEN (2:2) = ',' 
      fields terminated by ','
      trailing nullcols
      (
          id integer external,
          name char(32),
          con ":id || '-' || :name",
          dt date
      )
      ```
      
   
   2. 创建guc参数文件，如'/tmp/data/guc.txt'。
      ```
      set a_format_copy_version='s1';
      ```
      
   
   3. 创建数据文件，如'/tmp/data/data.csv'。
      ```
      1,OK,,2007-07-8
      2,OK,,2008-07-8
      3,OK,,2009-07-8
      4,OK,,2007-07-8
      43,DISCARD,,2007-07-8
      ,,,
      32,DISCARD,,2007-07-8
      a,ERROR int,,2007-07-8
      8,ERROR date,,2007-37-8
      ,,,,
       ,
      8,ERROR fields,,2007-37-8
      ,,,
      5,OK,,2021-07-30
      ```
      
   
   
   
   
2. 创建用户并授予使用权限。 
   ```
   CREATE USER load_user WITH PASSWORD '************';
   GRANT ALL ON SCHEMA public TO load_user;
   SELECT copy_summary_create() WHERE NOT EXISTS(SELECT * FROM pg_tables WHERE schemaname='public' AND tablename='gs_copy_summary');
   GRANT ALL PRIVILEGES ON  public.gs_copy_summary To load_user;
   SELECT copy_error_log_create() WHERE NOT EXISTS(SELECT * FROM pg_tables WHERE schemaname='public' AND tablename='pgxc_copy_error_log');
   GRANT ALL PRIVILEGES ON  public.pgxc_copy_error_log To load_user;
   \c - load_user
   Password for user load_user:
   ```
   
   
3. 创建目标导入表，如在gs_example数据库下创建loader_tbl表。 
   ```
   \c gs_example
   Password for user load_user:
   CREATE TABLE loader_tbl
   (
       ID   NUMBER,
       NAME VARCHAR2(20),
       CON  VARCHAR2(20),
       DT   DATE
   );
   ```
   
   
4. 进行导入。 
   退出当前登录连接。
   ```
   \q
   ```
   执行导入前，先确认gs_loader工具有可执行权限。确保当前路径有文件写入权限（gs_loader在处理过程中会生成一些临时文件，导入完成后自动删除）。
   ```
   gs_loader control=/tmp/data/loader.ctl data=/tmp/data/data.csv db=gs_example bad=/tmp/data/loader.bad guc_param=/tmp/data/guc.txt errors=5 port=8000 passwd=************ user=load_user -h 192.*.*.139;
   ```
   执行结果如下。
   ```
   gs_loader: version 0.1
    5 Rows successfully loaded. 
   log file is: 
    /tmp/data/loader.log
   ```
   其中/tmp/data/data.csv文件的前四行和最后一行被导入，第5行和第7行第二个字符不是','被忽略；第6行，第10行和第13行全部字段为空被忽略；第8行，第9行和第12行由于错误的字段值而不被导入。定义的'bad=/tmp/data/loader.bad'可以查看出错的行，执行结果回显的'/tmp/data/loader.log'记录了导入的日志信息。
   
   
表1gs_loader参数说明 
| 参数      | 参数说明                                                                                                                                          | 参数类型 : 取值范围            |
|:---|:---|:---|
| help    | 查看帮助信息。                                                                                                                                       | -                      |
| user    | 数据库连接用户（与-U等价）。                                                                                                                               | 字符串                    |
| -U      | 数据库连接用户（与user等价）。                                                                                                                             | 字符串                    |
| passwd  | 用户密码（与-W等价）。                                                                                                                                  | 字符串                    |
| -W      | 用户密码（与passwd等价）。                                                                                                                              | 字符串                    |
| db      | 数据库名称（必选，与-d等价）。                                                                                                                              | 字符串                    |
| -d      | 数据库名称（必选，与db等价）。                                                                                                                              | 字符串                    |
| host    | 指定正在运行服务器的主机名、Unix域套接字的路径、或者域名。接受以","分隔的字符串来指定多个主机地址，支持指定多个主机地址（与-h等价）。 当指定多个主机地址时，默认选择连接到主节点。 | 参考gsql --host参数        |
| -h      | 指定正在运行服务器的主机名、Unix域套接字的路径、或者域名。接受以","分隔的字符串来指定多个主机地址，支持指定多个主机地址（与host等价）。 当指定多个主机地址时，默认选择连接到主节点。  | 参考gsql --host参数        |
| port    | 指定数据库服务器的端口号。可以配置一个或多个，当配置一个时，所有的IP都使用同一个端口连接；当配置多个时，顺序与IP顺序相同，个数必须与IP数相等，当不相等时会报错（与-p等价）。                                                    | 参考gsql --port参数        |
| -p      | 指定数据库服务器的端口号。可以配置一个或多个，当配置一个时，所有的IP都使用同一个端口连接；当配置多个时，顺序与IP顺序相同，个数必须与IP数相等，当不相等时会报错（与port等价）。                                                  | 参考gsql --port参数        |
| create  | 是否创建pgxc_copy_error_log和gs_copy_summary表。由于当前版本会默认创建这两张表，因此该参数失去意义。保留仅为了兼容性。                                                                  | \[true, false\]，默认true |
| data    | 数据文件，可以指定多个，或者通配符多字符通配(\*)以及单字符通配(?)（必选）。                                                                                                     | 字符串                    |
| control | 控制文件名称（必选）。                                                                                                                                   | 字符串                    |
| log     | 日志文件名称。                                                                                                                                       | 字符串                    |
| bad     | 出错行以及详细情况记录文件名称，也可以指定目录，不指定时根据数据文件名生成。                                                                                                        | 字符串                    |
| errors  | 允许数据文件中出现多少出错行。                                                                                                                               | 整数，默认0                 |
| limit   | 指定最多导入的行数。                                                                                                                                    | 整数，默认无限大               |
   
![](https://support.huaweicloud.com/usermanual-gaussdb/public_sys-resources/caution_3.0-zh-cn.png)
- 参数均为小写，不支持大写，同时兼容gsql登录方式：-p端口号，-h主机，-d数据库，-U用户名，-W密码方式。
- 使用rows参数时，提交次数不要超过1000次，否则会对性能产生影响。提交次数约等于数据文件中数据行数除以rows参数取值。不指定rows参数时，rows无默认取值，表现为只进行一次提交，即所有数据都导入表中后进行一次事务提交。
- 小数据量频繁的提交会影响导入数据的性能，推荐合理配置rows参数的取值，保证每次提交的数据量大于5MB。对于常用的16U128G规格机器，一主两备部署场景下，向5个字段的表内导入13GB数据，排除网络影响，多次提交和单次提交（每次提交5MB数据）的速率基本持平，为10MB/s左右。
- 当前gs_loader仅支持数据文件中存在nul字符时的兼容，不支持ctl控制文件中存在nul字符。ctl文件中存在nul字符会存在不可预期的问题。
 
其他参数说明以及控制文件语法请参见《集中式版工具参考》"[gs_loader](https://support.huaweicloud.com/tg-gaussdb-cent-v8/gaussdb-38-0011.html)"章节。
