关于数据导入(Bulk Load 模式)

最近更新时间:2025-12-24 12:03:42

我的收藏

工具简介

TDSQL Boundless 支持以 bulk load 的方式向数据库快速导入数据。相比于执行传统 SQL 普通事务写入的方式,bulk load 快速导入模式在性能上通常提升5~10倍以上,适合在业务上线阶段用作迁移现有的大型数据库到全新的 TDSQL Boundless 集群。
目前支持用 INSERT INTO / REPLACE INTO 语句进行 bulk load 导入数据。

使用限制

语法层面
SET SESSION tdsql_bulk_load = ON,即 bulk load 模式需要打开。
仅优化 INSERT INTO/ REPLACE INTO语句,其他语句不支持 bulk load 模式。
INSERT INTO/ REPLACE INTO形式的 SQL,必须有多个 VALUES。如果只有一行数据,不支持 bulk load 模式。
INSERT INTO SET/ REPLACE INTO SET形式的 SQL 只能写入一行数据,不支持 bulk load 模式。
不优化 INSERT INTO ... ON DUPLICATE KEY UPDATE。因为 bulk load 模式下不会去检测已存在的 primary key,也就无法进行UPDATE操作。
对于INSERT INTO,实际上执行的是REPLACE INTO语法。即当导入的新数据与旧数据存在主键冲突时,并不会报错,而是直接静默地用新数据把旧数据覆盖掉。
对于含有IGNORE语法的 SQL 语句(INSERT INTO ... IGNORE ),需要提前 SET SESSION tdsql_bulk_load_allow_insert_ignore = ON,否则无法走 bulk load 导入。
对于含有IGNORE语法的 SQL 语句(INSERT INTO IGNORE),bulk load 导入时,需要由源端数据保证数据唯一性,即导入的新数据与旧数据不存在主键冲突,导入的新数据之间也不存在主键冲突。否则,由于 bulk load 模式下,主键数据会被静默地覆盖掉,只保留一行,这会违反IGNORE语法(即丢弃新数据保留旧数据)。
二级索引
当表上有 secondary index 二级索引时,需要提前 SET SESSION tdsql_bulk_load_allow_sk = ON,否则无法走 bulk load 优化。
当表上有 secondary index 二级索引时,bulk load 模式下需要由源端数据保证数据唯一性,即导入的新数据与旧数据不存在主键冲突,导入的新数据之间也不存在主键冲突。否则,由于 bulk load 模式下,主键数据会被静默地覆盖掉,只保留一行,但是二级索引数据编码后的 key 是没有唯一性的,就会出现二级索引数据的新旧两条记录都被保存下来了,导致主键和二级索引不一致。
对于需要建立 secondary index 二级索引的表,在 21.x 或之后的版本,用 bulk load 导数据时,优先推荐建表时先不建立 secondary index。待导入完成后,再创建 secondary index,创建 secondary index 的过程可以开启 fast online DDL 优化(需要手动开启),性能上会更好,而且可以绕过“源端数据唯一性”的限制。
当表上有 unique secondary index 唯一二级索引时,需要由源端数据保证数据唯一性,即既不存在主键冲突,也不违反二级索引数据的唯一性。否则会导致主键和二级索引不一致,或者打破二级索引数据唯一性的约束。
其他限制
系统表不支持 bulk load 模式。因为系统表不应该发生大规模写入,而且一旦系统表有问题,集群将无法启动。因此系统表采用更加稳健的写入路径。
存在触发器的表,不支持 bulk load 模式导入。
bulk load 模式目前与 DDL 是互斥的。即表上若存在进行中的 DDL,不支持 bulk load 模式;若正处于 bulk load 模式下导数据,新的 DDL 请求会被拒绝。
通过 bulk load 模式导入的数据,不会生成 binlog,不会同步到灾备集群的备实例。

运行环境要求

建议部署单独的导入机(即 MyLoader 将数据发往的目标节点),在预规划 RG 分布时,导入机上不放置 RG。导入完毕后,可以通过 RG 迁移(打开 MC 自动均衡)将 RG 副本重新平衡到导入机上,相当于把导入机重新作为一个普通的存算混合节点;也可以下线裁撤掉导入机。这是因为独占 IO 和 CPU 可以提供更好的导入性能。
内存和 CPU:导入机建议使用16核以上的 CPU 和64GB以上的内存以获得更好的性能。
存储空间:导入机至少需要(事务大小 × 并发数)的存储空间,通常与数据存储节点保持一致即可。
其他配置与集群中普通的混合节点或者数据存储节点保持一致即可。

工作原理

普通事务写入流程

数据在事务提交前会暂存在事务上下文的 write batch 中。进入提交阶段,write batch 中的数据会先落盘形成事务日志,通过 raft 协议同步到各副本所在节点。形成多数派后,数据会先写入内存中的 memtable 结构中,memtable 攒满后会 flush 落盘形成 SST 数据文件。SST 文件以 LSM-tree 结构进行分层组织存放,通过后台异步线程执行 compaction 操作,将数据进行合并和清理。


Bulk Load 写入流程

Bulk load 导入的写入流程尽量绕过了普通事务较为冗长的写入链路,直接将数据写入到压缩的数据文件中。
具体流程:
1. 接收到 bulk load 事务写入请求的节点(源节点)会先将 SQL 语句解析和编码成 key-value(KV)。
对于已有序的数据:直接写入到外部 SST 文件中。
对于无序的数据:先写到临时数据文件中,然后进行外部归并排序,生成外部 SST 文件。
2. bulk load 事务进入提交阶段后,源节点从 MC 控制节点拉取最新的 replication group(RG)路由信息,确定外部 SST 文件最终所属的 RG 及副本位置
3. 根据 RG 路由信息,源节点将外部 SST 文件发送到 RG 副本所在节点(数据节点)。
4. 确认外部 SST 文件被数据节点全部接收且校验成功后,源节点向 RG leader 数据节点发送 bulk load 事务提交请求,由 RG leader 数据节点同步一条 bulk load commit log(Raft 日志),日志形成多数派后,通过执行或回放这条日志,RG 副本所在数据节点将外部 SST 文件直接插入到 LSM-tree 的合适位置。至此,数据写入到了数据库中。
与普通事务写入流程相比,bulk load 写入流程性能优化关键点:
不进行事务冲突检测。
无需将数据临时驻留在内存 write batch 中,而是直接落盘写入 SST 数据文件。
不需要先将数据落盘到事务日志并同步(注意:虽然 bulk load 事务也会写一条 commit log 用于维持主备数据写入一致,但并不需要将事务数据序列化到日志中,仅同步一些必要的元信息)。
SST 数据文件无需通过 flush、compaction 操作由 LSM-tree 的最上层进入,而是直接将外部 SST 文件尽量插入到 LSM-tree 的尽量底层的位置。
这些 bulk load 所做的针对性优化,显著减少了 CPU、内存和 I/O 资源,是导入性能提升的关键点。