背景:
本案例是 2 年前的存货,用户实际使用的是 SQL Server,需要将数据从 SQL Server 迁移到 TiDB。数据同步通过 Kettle 完成,但性能非常低,用户希望提高同步效率。术业有专攻,我们既不熟悉 SQL Server,也不熟悉 Kettle,但我们可以学习(一部分)。因此,上游改用 MySQL 来进行测试。
优化结论:
在实验环境中,数据同步的初始速度为 12 条/秒。但用户环境已经实施过优化策略1,因此预计在所有优化策略都实施后,数据同步速度可以提高约 243 倍以上。
注:表格内均为实验环境数据,实际生产的表现会高很多。
优化测试过程:
初始测试架构
IP |
组件 |
172.16.201.17 |
5.7 MySQL |
联想笔记本 |
9.3 kettle |
172.16.201.71 |
5.4 TiDB |
PS:为方便测试,源端没有选用 sqlserver 做测试,但优化原理是一致的。
sysbench 制作 1000W 行的 sbtest1 表(体积 2.3G),表结构如下:
CREATE TABLE `sbtest1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`k` int(11) NOT NULL DEFAULT '0',
`c` char(120) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`pad` char(60) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */,
KEY `k_1` (`k`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=xxx;
单表从 MySQL 全量同步到 TiDB, 组件参考用户的源端使用表输入,目标端使用“插入/更新”, 这时同步效率只有 12 条每秒,性能瓶颈在网络(kettle 部署在外网,跨外网)。
优化网络交互
kettle 部署到上游 MySQL 服务器的同步效率为 130 条/s;
kettle 部署到下游 TiDB 服务器的同步效率为 133 条/s;
区别并不大,那么下面的测试 kettle 选择部署到下游 TiDB。
参考执行命令
sh /ssd/data-integration/pan.sh -file=/ssd/kettle0901/0901test.ktr -log=/ssd/kettle0901/kettle01.log
因方案是停业务同步到一个临时 schemas,理论上都是 insert 没有冲突,可以选上“不执行任何更新”,不过要确保其他转换任务都不会操作一样的表。
从 12 条/s 提升为 155 条/s,性能约为原来的 13 倍,这个模式是用户环境的现状。
组件调整为“表输出”
既然方案是停业务同步到一个临时 schema,理论上都是 insert 没有冲突,那么没必要使用“插入/更新”组件,这个组件的性能非常低,我们改为“表输出”组件。
这项优化性能提升是巨大的,从 155 条/s 提升为 466 条/s,性能约为原来的 3 倍。
修改任务的并行度
默认无并行,下面测试 4 并行的速度
这项优化性能提升是巨大的,从 466 条/s 提升为 1603 条/s,性能为原来的 3.4 倍。
JDBC 参数优化
源端
useServerPrepStmts=true
cachePrepStmts=true
defaultFetchSize=5000
目标端
rewriteBatchedStatements=true
useCompression=true
useServerPrepStmts=false
defaultFetchSize=5000
这项优化性能提升是巨大的,从 1603 条/s 提升为 9248 条/s,性能为原来的 5.7 倍。 PS: 组件为"插入/更新",则这项是负优化。
优化 commit
这项优化性能提升是巨大的,从 9248 条/s 提升为 38666 条/s,性能为原来的 4.18 倍。
优化 kettle 内存
测试大表如果慢,可以尝试调大内存。
vim /ssd/data-integration/spoon.sh
#以下这段代码数值调大
PENTAHO_DI_JAVA_OPTIONS="-Xms1024m -Xmx2048m"