暂无图片
暂无图片
3
暂无图片
暂无图片
暂无图片

使用 LOAD 命令加载 CSV 数据文件到 OceanBase 数据库

2023-11-23
361

OceanBase MySQL 的 load data 命令和 MySQL 的 load data 命令相同,不过需要将 csv 文件放到 OBServer 节点机器上。 OceanBase 数据库暂时不支持加载本地文件,该功能尚在研发中。

LOAD 语法

LOAD DATA
  [/*+ parallel(N) load_batch_size(M)*/]
    INFILE 'file_name'
    [REPLACE | IGNORE]
    INTO TABLE tbl_name
    [{FIELDS | COLUMNS}
        [TERMINATED BY 'string']
        [[OPTIONALLY] ENCLOSED BY 'char']
        [ESCAPED BY 'char']
    ]
    [LINES
        [STARTING BY 'string']
        [TERMINATED BY 'string']
    ]
    [IGNORE number {LINES | ROWS}]
    [(col_name_var
        [, col_name_var] ...)]
    [SET col_name={expr | DEFAULT},
        [, col_name={expr | DEFAULT}] ...]

LOAD 原理

Load Data 目前可以对 CSV 格式的文件进行导入,导入的流程如下:

  1. 解析文件:OceanBase 数据库根据用户输入的文件名,读取文件中的数据,并且根据用户输入的并行度来决定使用并行或者串行解析输入文件中的数据。
  2. 分发数据:由于 OceanBase 数据库是分布式数据库系统,各个分区的数据可能分布在各个不同的 OBServer,Load Data 会对解析出来的数据进行计算,决定数据需要被发送到哪个 OBServer。
  3. 插入数据:当目标 OBServer 收到发送过来的数据之后,在本地执行 insert 操作把数据插入到对应的分区中。

为提高 Load Data 语句的性能,您可以执行加载数据的并行度。Load Data 在解析文件、计算分区和数据分发阶段均可多个线程并行工作。

为了避免分布式事务对性能的影响,Load Data 会按照分区将数据分组,并分发到 OBServer 上进行多次写入,每次写入开启一个独立的事务,写入的数据来源于一个分组。如果在 Load Data 语句执行过程中出现了错误,您需手工删除已经被加载的数据。如果导入数据文件很大,每个节点插入数据的时间可能会很长,请根据需要调整 ob_query_timeout 参数。

Load Data 提供了不同选项支持用户不同的需求,目前支持的选项有:

  • 并行度 / *+ parallel(N)* / 选项指定加载数据的并行度,默认值是 N=4,建议使用的值范围是 [0 ~ 租户的最大 CPU 数]。

    load data /*+ parallel(4) */infile '/home/admin/a.csv' into table t
    
  • 批量 / *+ load_batch_size(M)* / 选项指定每次插入的批量大小,默认是 M=1000。根据导入数据行的总长度调整 M 的大小,建议使用的范围是 [100-1000]。

  • 输入文件 INFILE 'file_name' 关键字指定输入文件的路径和文件名,目前 Load Data 只支持加载 OBServer 本地的输入文件。所以,您需在导入之前把文件拷贝到某一个 OBServer 所在机器上,并在文件所在的 OBServer 运行 Load Data 语句。

  • 目标表索引 为了提高导入效率,建议先建基础表,待导入完成后,再创建表的索引。对全局索引,务必要导入之后再创建,否则可能会报 not support 错误。

  • 执行权限 您需要授予权限才能访问机器上文件。授予权限有两步:

  1. 修改安全文件所在路径 您可将安全文件路径设置为空,即无需检查。设置后需退出当前会话并重新登录方可生效。

    set global secure_file_priv = "";
    
  2. 对用户授予权限 您可执行下述命令在 MySQL 模式下为用户授予 file 权限。

    `grant file on *.* to USER_NAME;`
    
  • 重复数据处理 Replace 表示将表中原有的数据替换为输入文件中的数据。Ignore 表示忽略重复的数据。 Load Data 通过表的主键来判断数据是否重复,如果表不存在主键,那么 Load Data 语句就无法判断数据是否重复,replace 和 ignore 选项没有区别。 如果您不指定该选项,在发现重复数据时,Load Data 语句将把错误的数据记录到日志文件中。
  • 目标表选项 NTO TABLE tbl_name 关键字用于指定目标表名称。Load Data 支持分区表和非分区表。
  • 字段格式 字段格式用来指定输入文件的各个字段的分隔符选项,通过 Fields\|Columns 子句来指定。其中:
    • Terminated By 关键字用来指定字段的分隔符。
    • Enclosed By 关键字指定每个字段的开始和结束是否包含特定的字符。
    • Escaped By 关键字用来指定字段中的通配符。
  • 行格式 行格式指定输入文件中每一行的开始和结束字符,通过 Lines 子句设置。其中:
    • Starting By 用于指定每一行开始的字符。

    • Terminated By 用于指定每一行的结束字符。

    • IGNORE number {LINES \| ROWS} 子句指定忽略掉输入文件的前 number 行数据。

      load data /*+ parallel(4) */infile '/home/admin/a.csv' into table t fields terminated by ',' lines terminated by '\n';
      

日志文件

如果导入的过程中出现了错误,基于 Load Data 的设计,出现错误的 insert 语句会被回滚,并且 Load Data 语句会在 OBServer 安装路径的 log 子目录下产生名称为 obloaddata.log 的日志文件,以下是一个日志文件的示例:

Tenant name: mysql
File name: /home/admin/a.csv
Into table: `test`.`t`
Parallel: 1
Batch size: 1000
SQL trace: YD7A20BA65670-0005AADAAA3CAB52
Start time: 2020-07-29 21:08:13.073741
Load query:
load data infile '/home/admin/test.csv' into table t fields terminated by ',' lines terminated by '\n'

Row ErrCode ErrMsg
1 1062 Duplicated primary key
2 1062 Duplicated primary key

日志中包含 Load Data 产生的任务的基本信息,例如:租户名、输入文件名、目标表名、并行度和使用的 Load Data 命令。并且以行为单位给出具体错误的信息。

示例

$ mysql -h127.1 -u****@obmysql#obdemo -P2881 -p123456 -c -A test -Ns
MySQL [test]> select * from t1;
MySQL [test]> load data infile '/tmp/t1.csv' into table t1 fields terminated by ',' enclosed by '"' lines terminated by '\n' ;
MySQL [test]> select * from t1;
1        a b   a b
2        a,b   "a b"
3        a\nb a \nb
4        a\\b  "a\\b"
MySQL [test]>

说明

数据导入推荐直连进行,如通过 OBProxy 代理可能由于分发机制导致找不到数据、文件等错误。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论