MySql的JDBC驱动不支持批量操作(已结)

MySql连接的url中要加rewriteBatchedStatements参数,例如

String connectionUrl="jdbc:mysql://192.168.1.100:3306/test?rewriteBatchedStatements=true";

还要保证mysql JDBC驱的版本。MySql的JDBC驱动的批量插入操作性能是很优秀的。

MySql的JDBC驱动,不是真正支持批量操作的,就算你在代码中调用了批量操作的方法,MySql的JDBC驱动也是按照一般操作来处理的。

直觉告诉我,应该是一些简单的设置问题,事实上最后得到的结果也是如此的。

带着解决这个疑惑的想法,依据大家之前得到的一些结果,信息,开始测试

工具:

eclipse-3.6, mysql-5.1.48, mysql-jdbc-driver 5.1.11, mysql workbench前面说过了,我直觉认为代码不会有问题,所以先着手改善mysql 的服务器配置,innodb的设置。改了几个参数,都没有什么效果。加大了日志缓存,只是提高到7000多毫秒。最后甚至很多歪门邪道的设置都大胆用了,一度让mysql 无法启动。。。最终都收效甚微,这个步骤大概试了将近一个小时。

这条路看来是走不通了。。得寻找别的方法

冷静下来想想,其实从代码中应该是可以发现些端倪

楼主的非batch代码中,每次调用 execute() 其实是会通过网络发送一条语句到服务器端的,是不会在客户端排队攒着的。

因为这个方法必须返回一个结果。它必然跟服务器发生了一次交互。

而在batch处理的代码中,其addBatch 就是无返回值,它提供了一个可能就是在客户端将语句缓存排队攒着,最后executeBatch时才发送到服务器端。

用代码可以证明,在batch处理方法的代码中,在 executeBatch, 及 commit 方法执行前,分别安插两条打印时间语句:

Java代码

System.out.println("before executeBatch. "+ (System.currentTimeMillis()-a)+" ms");

prest.executeBatch();

System.out.println("before commit. "+ (System.currentTimeMillis()-a)+" ms");

conn.commit();

System.out.println("before executeBatch. "+ (System.currentTimeMillis()-a)+" ms"); prest.executeBatch(); System.out.println("before commit. "+ (System.currentTimeMillis()-a)+" ms"); conn.commit();

在我机器上的结果是,

Java代码

before executeBatch.279ms

before commit.7922ms

MySql批量插入10万条记录用时7923ms

before executeBatch. 279 ms before commit. 7922 ms MySql批量插入10万条记录用时7923 ms

说明客户端在攒语句时,相当的快,279毫秒就完成了,但在 executeBatch 这个方法的调用过程中,花费了 7920  减 去 279 的毫秒数。大部分都耗在这里了。 最后提交事务非常快,1毫秒而已

想想看,前边说过,非batch和batch的处理几乎是一样的时间。

可不可以先假设 batch 的方式与非batch一样,每一条insrt语句事实上均是单独发往服务器的呢?

浏览下源代码吧。

好几位兄弟都描述了源代码,直接从那几个类入手吧,事实上关键的类是这个 com.mysql.jdbc.PreparedStatement

先看了其中的 addBatch 方法,没有任何问题,只是将语句添加进入一个 List 中保存。

那么 executeBatch 呢?

再贴一下吧, 关键看其中的这部分,顺带说一下, 这个mysql-jdbcdriver的源代码是 5.1.13的

Java代码

try{

clearWarnings();

if(!this.batchHasPlainStatements

&&this.connection.getRewriteBatchedStatements()) {

if(canRewriteAsMultiValueInsertAtSqlLevel()) {

returnexecuteBatchedInserts(batchTimeout);//执行路径之一

}

if(this.connection.versionMeetsMinimum(4,1,0)

&& !this.batchHasPlainStatements

&&this.batchedArgs !=null

&&this.batchedArgs.size() >3/* cost of option setting rt-wise */) {

returnexecutePreparedBatchAsMultiStatement(batchTimeout);//执行路径之二

}

}

returnexecuteBatchSerially(batchTimeout);//执行路径之三

}finally{

clearBatch();

}

try { clearWarnings(); if (!this.batchHasPlainStatements && this.connection.getRewriteBatchedStatements()) { if (canRewriteAsMultiValueInsertAtSqlLevel()) { return executeBatchedInserts(batchTimeout); //执行路径之一 } if (this.connection.versionMeetsMinimum(4, 1, 0) && !this.batchHasPlainStatements && this.batchedArgs != null && this.batchedArgs.size() > 3 /* cost of option setting rt-wise */) { return executePreparedBatchAsMultiStatement(batchTimeout); //执行路径之二 } } return executeBatchSerially(batchTimeout); //执行路径之三 } finally { clearBatch(); }

其实最终,executeBatch 的执行路径有三种可能。代码中我已标出来

不小心按了提交了,继续编辑此回复吧。代码不算太复杂,但是有一个参数能帮助我们更快的确定mysql的batch工作机制,那就是

mysql jdbc driver 的connection url, 其中有一个参数是: rewriteBatchedStatements

完整的参数参考看这里:http://ftp.ntu.edu.tw/ftp/pub/MySQL/doc/refman/5.1/en/connector-j-reference-configuration-properties.html

rewriteBatchedStatements 参数默认为false, 需要手工设置为true,设置方式大概像这样:

Java代码

String connectionUrl="jdbc:mysql://192.168.1.100:3306/test?rewriteBatchedStatements=true";

String connectionUrl="jdbc:mysql://192.168.1.100:3306/test?rewriteBatchedStatements=true";

默认时候,rewriteBatchedStatements=false时,执行路径会跳到 executeBatchSerially,此方法内部将语句一条条发送,与非batch处理简直一样,所以慢,就在这里了。

当设为 true时,会执行executeBatchedInserts方法,事实上mysql支持这样的插入语句

Sql代码

insertintot_user(id,uname)values(1,'1'), (2,'2'), (3,'3') ....

insert into t_user(id,uname) values(1, '1'), (2,'2'), (3, '3') ....

所以,当rewriteBatchedStatements=true时, 楼主的例子会被编译为以上形式,当然values里全是?, mysql 客户端会对这些值添加参数. 这样的方式当然就快很多了。

其实到现在还不太了解 batch 处理时,执行计划这个概念,不过我猜 mysql 可能并没有缓存执行计划。而只是将这些语句组合起来了。

所以如果是这样,他的机制与oracle可能是有所不同的,还不是达到最高效的机制,也许这就是开源与商业的区别吧。

我们如果想更深入了解,只能借助于一些服务器端监视工具,sql分析工具了。

写贴子过程断断续续给打扰了,本来还有一些可以写更详细的,就留给大家自己去探索了,包括,如果调用addBatch(String sql)后,则仍会按照 executeBatchSerially 方式执行,包括何时执行 executePreparedBatchAsMultiStatement,都可以继续深入了解。

后记,当使用 update 时,会执行 executePreparedBatchAsMultiStatement,但是如果攒的语句太多,会导致 mysql 崩溃. 我的测试中10000条update不会有事,20000时,mysql 就崩掉了。

分享到:

2011-11-17 15:19

浏览 1569

分类:数据库

评论

mysql5批处理_转关于mysql5.5 的批处理讨论(转载)相关推荐

  1. mysql5.6.27_Centos上安装Mysql5.6.27多实例

    CentOs 6.4 Mysql5.6.27 CentOs6.4 Mysql5.6.27 卸载系统mysql: rpm -qa|grep -i mysql rpm -e --nodeps xxx # ...

  2. mysql5.1win7_免安装版mysql5.1.57在win7下成功配置

    mysql下载回来之后解压到D:/mysql-5.1.57-win32,把D:/mysql-5.1.57-win32/bin加入到系统环境变量Path中. 然后需要简单的配置mysql数据库,把my- ...

  3. 编译安装mysql5.5.39_编译安装MySQL5.5

    防伪码:没有相当程度的孤独是不可能有内心的平和. 1.测试环境 主机名 IP 系统 MySQL版本 MySQL-00 192.168.10.23 CentOS release 6.9 (Final) ...

  4. centos7.3 mysql5.7_CentOS7.3 yum install MySQL5.7

    1.更新 yum mysql5.7 源 2.yum mysql 源配置 禁用MySQL5.6的源:#yum-config-manager --disable mysql56-community 启用M ...

  5. linux安装mysql5.6整套_Linux安装Mysql5.6

    由于安装的mysql8.0和其他服务器的数据库(版本5.1.30)由于版本差异过大,无法通信,因此需要安装一个中间版本5.6,但是它的安装过程和mysql8.0安装略有不同. 解压文件 // 解压文件 ...

  6. centos7下源码安装mysql5.6_Centos7 源码安装mysql5.6

    mysql下载 谷歌 mysql->community->mysql community server->mysql community server 5.6->Select ...

  7. 安装mysql5.5.37_002. Centos7安装mysql5.5.37

    (百度网盘的连接地址使用wget下载不了) 4. 将上面三个包, 传到服务器上, 并解压 [root@iZ25bdzgev8Z mysql-5.5.37]# tar xvf mysql-5.5.37. ...

  8. Win7全自动精简批处理_温柔处理极速修正版/暴力剩女工程测试版

    2011htpcfans 发表于 2012-5-11 http://bbs.wuyou.net/forum.php?mod=viewthread&tid=210269&highligh ...

  9. sql程序调用批处理_批处理学习之常用命令

    Echo命令 功能:显示信息,设置命令回显打开或关闭 格式:ECHO [ON|OFF][要显示的字符] 例题 echo 你好 echo off      ren关闭命令回显,(批处理程序第一行都加这行 ...

最新文章

  1. 服务器ldap认证配置
  2. 《深入浅出WPF》笔记——事件篇
  3. 一位读者刚刚收割阿里、腾讯等大厂Offer,他说这些话一定要和你们说一下
  4. 2017年天津市大学生数学竞赛试题 (理工类)
  5. java添加按钮点击事件_如何为odoo 10中的按钮点击事件添加一个java脚本处理程序?...
  6. 前端笔记-css实现web自适应(当像素小于xx时隐藏此div)
  7. 每天进步一点点《ML - K-means》
  8. jstl错误:According to TLD or attribute directive in tag file, attribute value does not accept any expr
  9. php不使用copy()函数复制文件的方法
  10. NB-IOT开发实战
  11. vs2015完全卸载+重装 成功解决 未能加载xx包、未能安装编译器等问题
  12. linux常用命令清单
  13. 动态规划 TSP 问题
  14. 如何看待IT培训这件事情?IT培训出来的人都一无是处吗?
  15. python中输入字符串_python如何输入字符串
  16. 【it修真院】代码生成
  17. 为什么阿里会选择 Flink 作为新一代流式计算引擎?
  18. 使用vue-video-player实现直播
  19. 在贫民窟住了 29 年,我成为印度第一个 GitHub star
  20. 【xla】六、【构图阶段】xlaRunOp

热门文章

  1. MySQL应用安装_mysql安装和应用
  2. CVE-2013-4547 文件名逻辑漏洞
  3. cad求和插件_黑科技 | 无BIM建模下平面CAD自动生成门窗表
  4. c++生成光栅条纹程序_共享屋:一文让你认识光栅尺和编码器
  5. c# mvvm模式获取当前窗口_AWTK-MVVM 介绍
  6. 【SSM面向CRUD编程专栏 3】关于黑马程序员最全SSM框架教程视频,P37集老师跳过的模块创建以及tomcat下载安装配置和运行等诸多问题
  7. 如何编写一个shell脚本
  8. MySQL为什么要set names
  9. Angular实现图片点击缩放组件
  10. 4-什么是Image和container