扫码阅读
手机扫码阅读

TiDB | 导入文档繁琐耗时?那我要说两句了

287 2023-09-07


TiDB

神州数码云基地

在 TiDB 上的尝试、调研与分享


本期内容

文档高效导入TiDB

在项目中我们经常会遇到数据导入的需求,比如把 txt 或者 csv 文件中的数据导入到 TiDB 集群当中。

这原本是件很简单的事,直到某次的项目中,这件事被限制在一个非常短的时间内,让人压力倍增...

这才意识到,一些简单的事情,才更应提升效率,腾出时间做更多有价值的事情!本篇内容则研究该如何更快、更加安全的把数据导入到 TiDB 中!

TiDB集群准备

在导入数据之前,TiDB 当然需要准备一下~万一出现写热点,或者事务过大导致导入过慢、甚至失败,进而导致规定时间内,数据没有导入完成,那岂不是功亏一篑了。

避免写热点

在大量数据插入场景中,大概率会出现写热点的情况,针对这种情况,我们必须提前做好对应。

S tep 1: 增加参数

  • SHARD_ROW_ID_BITS

  • pre_split_regions

```CREATE TABLE `t1` ( `id` int(11) NOT NULL,) shard_row_id_bits = 4 pre_split_regions = 4;```

/ 示例

S tep 2: 手动切分region

对于导入追加数据的场景,已有表结构并有历史数据时,需要手动切分region。我们可以使用 split-table-region 的方法来处理写热点的问题。


由于row_id是整数,所以根据指定的lower_valueupper_value以及region_num,可以推算出需要切分的key

TiDB先计算step(step=(upper_value-lower_value)/region_num),然后在lower_value upper_value之间每隔step区间切一次,最终切出region_numRegion

例如,对干表t如果想要从minInt64~maxInt64之间均匀切割出16个Reaion,可以用以下语包:

该语句会把表 t 从minlnt64到maxlnt64之间均匀切割出16个Region。(可以根据主键的大致范围设置相应数值代替上面的minlnt64和maxlnt64来切分Region。)

????需要注意的是,建表语句增加了 shard_row_id_bits 和 pre_split_regions 参数后,需要尽快开始向目标表导入数据,不然分割的空 region 可能会被 merge,导致出现写热点的问题。

避免大事务导致的OOM

在 TiDB 集群中,插入数据时,每条数据都会占用 tidb-server 节点的内存。


当一个事务中插入的数据量过大,就会导致节点使用过大内存出现 OOM 的情况。要解决大事务的问题,需要开启以下几个参数:

  • 在拓扑文件中加入:enable-batch-dml: true

  • SET @@GLOBAL.tidb_dml_batch_size = 20000;

  • SET @@SESSION.tidb_batch_insert = 1;

这三个参数需要配合使用,表示在一个 insert 的事务中,TiDB 会在内部把一个 insert 的大事务,按 20000 条数据拆分成一个个小事务分批提交,这样便能避免OOM 的情况。

(但也会无法保证 TiDB 的原子性和隔离性要求,所以这个需要大家根据自己的实际情况进行选择。)

文档导入测试

导入工具的选择

以下为不同工具的对比说明

Navicat

有非常好的交互界面,用户学习成本几乎是0,直接可以上手导入数据,Navicat 内部会对文件中的数据分批执行,速度也不慢,但是只能在windows系统中操作。

load data

MySQL 中的常规批量导入方式,可以指定十六进制分隔符,TiDB 中除 LOAD DATA...REPLACE INTO 语法之外,LOAD DATA 语句应该完全兼容 MySQL。

Lightning

这是非常推荐的一款逻辑批量导入数据的工具,可以直接把数据转换成键值对,并插入到 TiKV 中,所以这样导入数据理论上是最快的。

但是使用 lightning 也有一些不方便的地方,比如多次导入需要频繁修改配置文件,文件名称必须是“库名.表名”的形式,不能导入 txt 文件数据,如果导入失败需要手动修改 TiKV 集群为普通模式等等。

数据准备

这次测试我准备了四个不同数据量的 csv 文件,文件大小在 100MB 到 11GB :

表结构为:

```CREATE TABLE `sbtest` ( `id` int(11) NOT NULL AUTO_INCREMENT, `k` int(11) NOT NULL DEFAULT '0', `c` char(120) NOT NULL DEFAULT '', `pad` char(60) NOT NULL DEFAULT '', PRIMARY KEY (`id`) /*T![clustered_index] NONCLUSTERED */, KEY `k_1` (`k`)) shard_row_id_bits = 4 pre_split_regions = 4 ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin```

TiDB 集群准备

每台机器配置都是 8 vCore,32G内存,千兆带宽。配置有限,所有测试都在这个集群环境中进行测试。

测试结果

测试结果分析

总结

▶ Lightning 限制较多,但是功能也是最全的,local 模式的导入速度吊打其他导入工具。

▶ load data 支持 txt 文件数据的导入,而且也能自定义一些常规参数,比如字段分隔符等,导入速度仅次于 Lightning 的 local 模式。基于 load data 开发一个符合业务需求的脚本,要比直接用 Lightning 开发简单的多。

▶ 针对需要用到 Lightning 的功能,而且是增量数据导入的话,建议使用 Lightning 的 tidb 模式。

▶ Navicat 只推荐给初学者导入少量数据使用。

以上就是文档快速导入TiDB

的实践操作过程

希望能帮助到大家~

有更好的办法或疑问

欢迎加入社群一起讨论哦⬇


本期作者

后端开发工程师 蔡一凡


原文链接: http://mp.weixin.qq.com/s?__biz=Mzg5MzUyOTgwMQ==&mid=2247507621&idx=1&sn=a24d43a9363affdd87c0b27542254d56&chksm=c02fe503f7586c15a5014eeb32f02f12de3e585a76442e5dba5634adc19afca535e595af4fc4#rd