如何加速20亿条数据库表记录的跨库迁移?
优化20亿条记录跨库迁移速率的实战方案
兄弟,700条/分钟的速度处理20亿条数据?这得熬到猴年马月啊!我来给你捋几个能把速率拉上去的实招,都是实战中验证过的:
1. 立刻放弃逐行操作,全面改用批量处理
这是提升速率最核心的一步,没有之一:
- 读取源库时,别每次只拉1条,改成一次拉取1000-10000条(具体数量可以根据你的内存和数据库性能调整)。注意别用
LIMIT offset, size这种越往后越慢的分页,换成按iIndex的范围分段读取(比如WHERE iIndex BETWEEN X AND Y),或者用数据库游标来批量获取数据。 - 转换JSON的时候也批量搞,别单条序列化;写入目标库时用批量插入/更新语句,比如MySQL的
INSERT ... ON DUPLICATE KEY UPDATE,PostgreSQL的INSERT ... ON CONFLICT ... DO UPDATE,把几百上千条数据合并成1条SQL执行,能大幅减少网络往返次数和数据库锁的开销。
2. 给数据库做“性能按摩”,减少读写瓶颈
- 源库db1读取优化:给
q_iTable的iIndex、pIndex建联合索引,避免全表扫描拖慢读取速度;如果是MySQL,可以试试FORCE INDEX强制走索引;如果数据量实在太大,看看能不能把表分成几个分区,按分区分段读取。 - 目标库db2写入优化:暂时关掉
iTable的非必要索引和触发器——这些东西会在写入时额外消耗大量资源,等迁移完再重建就行。另外调整数据库的写入参数,比如MySQL把innodb_flush_log_at_trx_commit设为2(牺牲一点实时一致性换写入速度,迁移完成后改回默认值),增大innodb_buffer_pool_size让更多数据留在内存里。
3. 砍掉不必要的中间环节,减少转换开销
- 如果业务不是必须要JSON格式,直接跳过JSON转换!把源库查询到的结果直接映射成目标表的字段结构,直接构造批量SQL,省去序列化和反序列化的性能损耗——这一步能省不少CPU资源。
- 要是真的必须用JSON,换个更高效的序列化库,比如Java用Jackson、Python用ujson,而且一定要批量序列化,别单条处理。
4. 搞并行处理,把多核/多实例的性能榨干
把源数据分成多个独立的分片(比如按iIndex的哈希值或者范围分成10-20个分片),每个分片用一个独立的进程/线程去处理。这样可以同时进行读取、转换、写入操作,充分利用CPU和网络带宽,速率能直接翻好几倍。
注意:分片一定要划分清晰,别让两个进程同时处理同一段数据,避免冲突。
5. 优化校验逻辑,别让校验拖后腿
- 如果现在是逐行校验db2的数据,改成批量校验:先把db2中对应分片的
iIndex、pIndex数据批量拉出来,放到内存里做成哈希映射(比如用字典存iIndex对应的pIndex),然后和源库的批量数据做对比,一次性确定哪些需要插入、哪些需要更新,减少多次查询db2的开销。 - 要是校验逻辑比较复杂,试试把校验逻辑下推到数据库层面,比如用跨库JOIN直接对比两个库的数据(如果db1和db2支持跨库关联的话),直接生成需要插入/更新的数据集,让数据库来做这些脏活累活,比应用层快得多。
6. 实在不行,换用更底层的迁移工具
如果应用层优化到顶还是不够,别死磕自己写的脚本了,试试数据库原生的迁移工具:比如MySQL的mysqldump+mysqlimport,PostgreSQL的pg_dump+psql,这些工具都是底层实现,速率能达到几万甚至几十万条/分钟。要是需要增量同步,还可以用CDC工具比如Debezium,直接从数据库的binlog/WAL日志里同步数据,几乎能达到实时同步的速度。
内容的提问来源于stack exchange,提问作者Mooni
相关产品推荐
相关产品推荐

