网站管理员怎么做板块建设,青岛网站建设与设计制作,qq短网址生成,湖南省住房和城乡建设厅门户网站粗略的实验 最后 最近在压测一批接口的时候#xff0c;我发现接口处理速度比我们预期的要慢。这让我感到有点奇怪#xff0c;因为我们之前已经对这些接口进行了优化。但是#xff0c;当我们进行排查时#xff0c;发现问题出在数据库批量保存这块。
我们的项目使用了 myb… 粗略的实验 最后 最近在压测一批接口的时候我发现接口处理速度比我们预期的要慢。这让我感到有点奇怪因为我们之前已经对这些接口进行了优化。但是当我们进行排查时发现问题出在数据库批量保存这块。
我们的项目使用了 mybatis-plus 这个工具而批量保存我们是直接使用的 mybatis-plus 提供的 saveBatch 方法。在仔细研究了这个方法后我发现它并没有对批量插入进行优化而是直接循环插入数据。
我点进去看了下源码感觉有点不太对劲
我继续追踪了下从这个代码来看确实是 for 循环一条一条执行了 sqlSession.insert下面的 consumer 执行的就是上面的 sqlSession.insert:
然后累计一定数量后一批 flush。
从这点来看这个 saveBach 的性能肯定比直接一条一条 insert 快。
我直接进行一个粗略的实验简单创建了一张表来对比一波
粗略的实验 1000条数据一条一条插入 可以看到执行一批 1000 条数的批量保存耗费的时间是 121011 毫秒。 1000条数据用 mybatis-plus 自带的 saveBatch 插入 耗费的时间是 59927 毫秒比一条一条插入快了一倍从这点来看效率还是可以的。
然后常见的还有一种利用拼接 sql 方式来实现批量插入我们也来对比试试看性能如何。 1000条数据用手动拼接 sql 方式插入 搞个手动拼接 来跑跑下性能如何
耗时只有 2275 毫秒性能比 mybatis-plus 自带的 saveBatch 好了 26 倍
这时我又突然回想起以前直接用 JDBC 批量保存的接口那都到这份上了顺带也跑跑看 1000条数据用 JDBC executeBatch 插入 耗时是 55663 毫秒所以 JDBC executeBatch 的性能跟 mybatis-plus 的 saveBatch 一样底层一样。
综上所述拼接 sql 的方式实现批量保存效率最佳。
但是我又不太甘心总感觉应该有什么别的法子然后我就继续跟着 mybatis-plus 的源码 debug 了一下跟到了 mysql 的驱动突然发现有个 if 里面的条件有点显眼 就是这个叫 rewriteBatchedStatements 的玩意从名字来看是要重写批操作的 Statement前面batchHasPlainStatements 已经是 false取反肯定是 true所以只要这参数是 true 就会进行一波操作。
我看了下默认是 false。
同时我也上网查了下 rewriteBatchedStatements 参数好家伙好像有用我直接将 jdbcurl 加上了这个参数 然后继续跑了下 mybatis-plus 自带的 saveBatch果然性能大大提高跟拼接 SQL 差不多
顺带我也跑了下 JDBC 的 executeBatch 果然也提高了。
然后我继续 debug 来探探 rewriteBatchedStatements 究竟是怎么 rewrite 的
如果这个参数是 true则会执行下面的方法且直接返回
看下 executeBatchedInserts 究竟干了什么
看到上面我圈出来的代码没好像已经有点感觉了继续往下 debug。
果然sql 语句被 rewrite了
对插入而言所谓的 rewrite 其实就是将一批插入拼接成 insert into xxx values (a),(b),(c)...这样一条语句的形式然后执行这样一来跟拼接 sql 的效果是一样的。
那为什么默认不给这个参数设置为 true 呢
原来是这样的 如果批量语句中的某些语句失败则默认重写会导致所有语句都失败。 批量语句的某些语句参数不一样则默认重写会使得查询缓存未命中。
看起来影响不大所以我给我的项目设置上了这个参数 最后
稍微总结下我粗略的对比虽然粗略但实验结果符合原理层面的理解如果你想更准确地实验可以使用JMH并且测试更多组数如 500010000等的情况。 在处理 JDBC 的批量操作时有两个性能方面的关键点。首先需要注意将 rewriteBatchedStatements 设置为 true以提高性能。其次如果你倾向于手动拼接 SQL 语句你需要注意一次拼接的数量并进行分批处理。此外你也可以通过优化 SQL 查询语句的方式来提高性能。例如使用索引、避免使用 select * 等操作可以减少查询所需的时间和资源。还可以使用连接池来缓存数据库连接减少每次建立连接的时间和成本。总之通过细致地调整和优化你的数据库操作你可以显著提高应用程序的性能和稳定性。