mybatis批量更新比对
上次发现因为数据库获取新的连接超时,其实是对数据做存在更新不存在做插入。想到对于更新不同数据速度相差多少。
暂时有4种更新方法。
一个个更新
1 | update simple set code=#{item.code} |
采用batch批量更新,sql如上,只是批量提交请求。
拼装更新sql为一个大的sql
1 | <foreach collection="datas" item="item" separator=";"> |
对于mysql,需要添加allowMultiQueries=true参数
采用临时表关联更新
1 | update simple t, |
单线程性能比较
| 单个更新 | 批量提交 | 拼装sql | 临时表 | |
|---|---|---|---|---|
| 10w/1k | 122.9 | 63.99 | 13.2 | 3.87 |
采用的数据量是10w条数据,随机更新10w次,对于批量更新一次提交1000条数据,因为对比结果相差较大,多次测试同类型时间大致相差不大,未统计每次的数据
后续测试了100w条数据更新10w次,比对结果差不多。
多线程性能比较
| 总数/单次 | 单个更新 | 批量提交 | 拼装sql | 临时表 |
|---|---|---|---|---|
| 1w/1k | 68.44 | 57.37 | 45.23 | 出现死锁 |
| 1w/10 | - | - | - | 8.25 |
采用的数据量是10w条数据,随机更新1w次。对于临时表更新(一次1000),出现了死锁,应该是不同的线程里面更新的数据有一样的导致。改为10条后,多次测试未出现死锁,应该是一次更新数据量少了后,不容易重复。
多线程比对的时候需要设置自动提交,避免死锁。
普通索引更新(单线程)
| 总数/单次 | 单个更新 | 批量提交 | 拼装sql | 临时表 |
|---|---|---|---|---|
| 10w/1k | 445.71 | 1178.84 | 343.24 | 4.31 |
| 1w/1k | 47.67 | 42.36 | 35.25 | 1.13 |
| 1w/100 | 46.73 | 41.52 | 100.46 | 1.63 |
- ?建立普通索引后,如果普通索引更新字段结果如上,对于批量提交10w/1k耗时异常长(多次测试),暂时未找到原因。
普通索引更新(多线程)
| 总数/单次 | 单个更新 | 批量提交 | 拼装sql | 临时表 |
|---|---|---|---|---|
| 1w/1k | 71.47 | 68.44 | 47.59 | 死锁 |
| 1w/100 | 68.24 | 59.68 | 44.97 | 死锁 |
| 1w/10 | - | - | - | 9.03 |
对于多线程版本,比对和主键相差不太大
唯一索引(单线程)
和普通索引差不多,批量提交一样耗时异常长。
唯一索引(多线程)
| 总数/单次 | 单个更新 | 批量提交 | 拼装sql | 临时表 |
|---|---|---|---|---|
| 1w/1k | 87.17 | 58.65 | 47.54 | 死锁 |
| 1w/100 | 71.12 | 61.23 | 46.96 | 死锁 |
| 1w/10 | - | - | - | 9.67 |
对于单个更新发现相对普通索引性能更低了,不确认是否因为测试次数较少偶然导致。
总结
在测试过程中,并未多次测试取平均值,所以只能看到大概比对。常规情况性能比较 单次 < 批量 < 拼装sql < 临时表。
在测试过程了临时表性能相对其他方式性能有大幅度提高,只是会存在死锁情况,对于少量并发少量数据更新的情况下,优选临时表更新。同时临时表更新也支持Sharding-JDBC是一大优点。
批量提交相对单个更新性能优势并没有特别大,优势是只提交一次sql,后面只是多条参数给数据库,相比而言与数据库交互少。不过对于批量提交需要注意的是提交的参数需要一致,如果mybatis的xml中使用了foreach和if导致生成的参数不对,会导致执行失败。
因为批量提交原理是提交一个sql给数据库做预处理,后面提交参数,如果参数不一致就会导致执行异常。
对于拼装sql,如果单条sql更新的字段非常多,且mybatis的xml中如果有很多判断逻辑,导致最终生成的sql比较大(有很多空白行),如果拼装过多就会导致最终一次提交给数据库的sql过大,之前jvm分析中找到的sql就是采用的拼装,导出sql后文件有1M多。
对于超多字段更新情况下并未做参数,可能性能比对相差不是很大,不过也可能因为最后生成sql较大导致性能有差距。
本次参数过程中还缺少记录数据库cup、内存、磁盘占用情况。
测试代码地址:https://github.com/whhxz/blog-example/tree/main/mybatis-batch-handler-test