主题:MySql的JDBC驱动不支持批量操作(更新)
srdrm的回复非常好:)
mysql 虽然用得不多,公司一直用的mssql.
楼主的测试结果让人非常失望...
但mysql名气这么大,不太相信在这样的问题上会出现与oracle这么大的差距。
直觉告诉我,应该是一些简单的设置问题,事实上最后得到的结果也是如此的。
带着解决这个疑惑的想法,依据大家之前得到的一些结果,信息,开始测试
工具:
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 方法执行前,分别安插两条打印时间语句:
- System.out.println("before executeBatch. "+ (System.currentTimeMillis()-a)+" ms");
- prest.executeBatch();
- System.out.println("before commit. "+ (System.currentTimeMillis()-a)+" ms");
- conn.commit();
在我机器上的结果是,
- 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的
- 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 ) {
- 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,设置方式大概像这样:
- String connectionUrl="jdbc:mysql://192.168.1.100:3306/test?rewriteBatchedStatements=true";
默认时候,rewriteBatchedStatements=false时,执行路径会跳到 executeBatchSerially,此方法内部将语句一条条发送,与非batch处理简直一样,所以慢,就在这里了。
当设为 true时,会执行executeBatchedInserts方法,事实上mysql支持这样的插入语句
- 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 就崩掉了。
分享到:
相关推荐
Oracle MySQL JDBC驱动是连接Oracle数据库和Java应用程序的重要组件,它允许Java程序通过Java Database Connectivity (JDBC) API与MySQL数据库进行交互。Oracle公司为MySQL提供官方的JDBC驱动,确保了高效、稳定的...
MySQL JDBC驱动是Java开发者在与MySQL数据库交互时不可或缺的一个组件。JDBC(Java Database Connectivity)是Java编程语言的标准API,用于连接Java应用程序和各种类型的数据库,包括MySQL。MySQL JDBC驱动,也称为...
- SQL Server JDBC驱动支持JDBC API的所有核心功能,包括连接、查询、事务管理等,并提供了额外的特性,如批量更新、流处理和分布式事务支持。 2. MySQL JDBC驱动(也称为MySQL Connector/J): - MySQL JDBC驱动...
MySQL的JDBC驱动是连接Java应用程序与MySQL数据库的关键组件,它实现了Java Database Connectivity (JDBC) API,使得Java开发者能够方便地在Java程序中执行SQL语句,进行数据的读写操作。标题提及的是"mysql的jdbc...
MySQL JDBC驱动5.1版本虽然已较老旧,但仍然被广泛使用,尤其是在一些稳定且不需最新特性的项目中。然而,为了获得最新的功能、安全更新和性能提升,建议使用更现代的版本,如8.x系列。升级驱动有助于利用MySQL的新...
JDBC驱动包的使用不仅限于简单的CRUD操作,还支持存储过程、批量操作、连接池管理等复杂功能。在实际开发中,了解JDBC的性能优化技巧,如批处理、预编译的语句、连接池配置等,也是至关重要的。 总之,Java开发...
在MySQL 5.7版本中,JDBC驱动主要支持以下特性: - **连接池支持**:允许程序复用数据库连接,提高效率,减少资源消耗。例如,可以使用C3P0、HikariCP等连接池管理库。 - **预编译语句(PreparedStatement)**:预...
MySQL的JDBC驱动,全称为Java Database Connectivity ...随着MySQL的版本更新,JDBC驱动也会随之升级,以支持新的数据库功能和改进的API。因此,对于新项目,建议使用最新稳定版的JDBC驱动,以获得最佳的兼容性和性能。
MySQL JDBC驱动,也称为`mysql-connector-java.jar`,是用于连接Java应用和MySQL数据库的桥梁。它实现了JDBC API,使得开发者可以通过编写Java代码来执行SQL语句、处理结果集等。在项目中,需要将这个jar包添加到类...
`mysql-connector-java-8.0.12.jar` 是MySQL 8.0.12版本的JDBC驱动程序,支持最新特性,如JSON列类型、窗口函数、增强的加密功能等。要使用这个驱动,开发者需要在项目中引入该jar包,并配置相应的数据库连接URL、...
总结起来,这个压缩包提供的各种数据库JDBC驱动是开发过程中不可或缺的工具,它们简化了Java应用与数据库之间的交互,使得跨数据库平台的开发变得更加便捷。开发者可以根据自己的需求选择合适的驱动,遵循JDBC规范...
在 MySQL 8 中,JDBC 驱动程序实现了这个接口,使得 Java 开发人员能够编写代码来执行 SQL 查询、操作数据以及管理 MySQL 数据库。 首先,让我们深入了解 JDBC。JDBC 是一个 Java API,它定义了一系列的接口和类,...
例如,从5.x到8.x,MySQL引入了窗口函数、JSON数据类型、多线程复制等新特性,JDBC驱动随之进行了相应的支持。同时,连接器也不断进行性能提升,如减少网络通信、优化结果集处理等,以提高Java应用的数据库操作效率...
- **SQL Server**:微软的数据库管理系统,支持多种JDBC驱动,包括Type 4驱动如Microsoft JDBC Driver for SQL Server,它提供了高效、安全的Java到SQL Server的连接。 - **Oracle**:Oracle数据库通常使用Oracle ...
首先,我们需要了解MySQL JDBC驱动,也称为MySQL Connector/J。这是由MySQL官方提供的Java数据库连接器,它实现了Java.sql和javax.sql接口,使得Java应用程序能够通过标准的JDBC API与MySQL数据库进行通信。`mysql-...
对于批量插入或更新操作,JDBC提供了BatchUpdateException和addBatch()方法,可以提高效率。 总结,JDBC驱动是Java与SQLserver、Oracle、MySQL等数据库通信的关键组件。理解JDBC的工作原理,掌握其核心API的使用,...
**数据库的JDBC驱动** Java Database Connectivity (JDBC) 是Java平台中用于与关系数据库进行交互的一种标准接口。它是Java编程语言的一部分,允许应用程序通过Java代码执行SQL语句,进行数据查询、插入、更新和...
此外,随着Java版本的更新,新的JDBC驱动也会提供对Java新特性的支持,比如Java 8的日期和时间API,以及Java 9模块系统。 总之,`mysql-jdbc.jar`是Java开发者与MySQL数据库交互的核心工具,它简化了数据库操作,...
MySQL JDBC驱动,全称为MySQL Connector/J,是MySQL官方提供的用于Java应用程序与MySQL数据库进行交互的驱动程序。这个驱动遵循Java Database Connectivity (JDBC) API标准,使得Java开发者能够方便地在Java环境中...
9. **异步操作**:从MySQL 5.7开始,MySQL JDBC驱动支持异步查询,允许在等待查询结果时执行其他任务,提高应用的响应性。 在实际开发中,将`mysql-connector-java-5.1.25-bin.jar`添加到项目的类路径中,就可以在...