一、背景
项目在使用Datax将mysql数据同步到clickhouse时,jobContainer的速率一直卡在1M/S左右上不去。
二、日志
这是当前测试数据库同步400w数据的最高速度,可以看到写入速度为25000rec/s,平均每秒写入25000条记录,再仔细研究日志中的信息:
能够看出几乎大部分的耗时都在等待写的task上,那么是什么导致了这个原因呢?
三、配置
继续观察日志,可以看出写入每次都在25w条记录左右,一直无法突破这个上限。
介绍配置(个人释义,望指正):
job.setting.speed.channel: 控制job的channel数
job.setting.speed.byte:控制job总体的byte数
job.setting.speed.record:控制job总体的记录数
core.transport.channel.speed.channel:控制单个task的channel数
core.transport.channel.speed.byte: 控制单个task的byte数
core.transport.channel.speed.record: 控制单个task的记录数
content.reader.parameter.splitPk:指定了splitPk字段,DataX会将MySQL表中数据按照splitPk切分成n段。splitPk的字段必须是整型或者字符串类型。在mysqlreader中仅对int类型友好。
content.reader.parameter.connection.querySql:指定用于将源数据分段查询的SQL,按照指定的SQL将内容分为多个task,该配置项与splitPk一起声明会报错。
content.writer.parameter.batchSize: 看名字就知道,写入的批次大小,datax默认batchSize:2048
content.writer.partmeter.batchByteSize:写入批次的Byte大小,datax默认batchByteSize:32*1024*1024
以上是通过对每个配置项进行测试所得的能够影响本背景下的datax同步速率的主要配置。
四、解决
(1)之前通过查看日志得出了耗时都在等待写的阶段,所以我将batchSize和batchByteSize设置为较大的值,仅设置channel为10,再测试了一遍:
测试结果:
速率明显得到提高,试着在增大batchSize,此时已经发生报错,原因是与目标库连接超时,查看clickhouse日志发现:
发生I/O error,应该是测试环境承受不住过大的IO,该错误为偶发性。
(2)使用splitPk进行优化,将splitPk的键配置为分布均匀的int类型的键,去掉之前的writer中的batchSize和batchByteSize,channel还是10,测试:
可以看到SingleTableSplitUtil开始对配置中的键进行分割,分割后的每条语句代表一个task
通过splitPk来分割可以将一个job划分为多个task,测试的写入速度达到了80000rec/s
但是这个配置项的局限性也很显著,就是仅适用于int类型,且值分布均匀的情况,不适用本背景。
(3)通过querySql来自定义划分,优点:可以自定义,更灵活,缺点:需要对表结构足够了解,能够对表有较强的分割能力,且多表数据量大的话需要花时间去研究如何分割。我这里采用简单的测试,需要注意的是querySql和table、column配置不能同时存在:
展示测试结果:
可以看出job已经按照对应的SQL划分多个task
五、总结
针对此背景可以使用batchSize和batchByteSize指定读取批次的size,splitPk指定划分的键,split算法由datax自动完成,querySql自定义划分SQL,灵活针对不同的表结构。
有不对的地方还望评论区讨论,感谢datax优化之reader提速-详细经历_datax 调优_cclovezbf的博客-CSDN博客
其中详细讲解了task的分割,从源码的角度详细解读各配置的优先级,本篇由此而来...