Java不写文件,LOAD DATA LOCAL INFILE大批量导入数据到MySQL的

大家都知道当插入大批量数据MySQL的时候,MySQL使用load data local infile 从文件中导入数据比insert语句要快,MySQL文档上说要快20倍左右。但是这个方法有个缺点,,就是导入数据之前,必须要有文件,也就是说从文件中导入。这样就需要去写文件,以及文件删除等维护。某些情况下,比如数据源并发的话,还会出现写文件并发问题,很难处理。那么有没有什么办法,可以达到同样的效率,直接从内存(IO流中)中导入数据,而不需要写文件呢?前段时间,去MySQL社区的时候发现了这样一个方法:setLocalInfileInputStream(),此方法位于com.mysql.jdbc.PreparedStatement 类中下面是具体实现:

通过使用 MySQL JDBC 的setLocalInfileInputStream 方法实现从java InputStream中load data local infile 到MySQL数据库中。

准备测试表SQL如下:

use test;CREATE TABLE `test` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `a` int(11) NOT NULL, `b` bigint(20) unsigned NOT NULL, `c` bigint(20) unsigned NOT NULL, `d` int(10) unsigned NOT NULL, `e` int(10) unsigned NOT NULL, `f` int(10) unsigned NOT NULL, PRIMARY KEY (`id`), KEY `a_b` (`a`,`b`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8

Java代码如下:

package com.seven.dbTools.DBTools;import java.io.ByteArrayInputStream;import java.io.InputStream;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.SQLException;import org.springframework.jdbc.core.JdbcTemplate;import javax.sql.DataSource;import org.apache.log4j.Logger;/** * @author seven * @since 07.03.2013 */public class BulkLoadData2MySQL {private static final Logger logger = Logger.getLogger(BulkLoadData2MySQL.class);private JdbcTemplate jdbcTemplate;private Connection conn = null;public void setDataSource(DataSource dataSource) {this.jdbcTemplate = new JdbcTemplate(dataSource);}public static InputStream getTestDataInputStream() {StringBuilder builder = new StringBuilder();for (int i = 1; i <= 10; i++) {for (int j = 0; j <= 10000; j++) {builder.append(4);builder.append("\t");builder.append(4 + 1);builder.append("\t");builder.append(4 + 2);builder.append("\t");builder.append(4 + 3);builder.append("\t");builder.append(4 + 4);builder.append("\t");builder.append(4 + 5);builder.append("\n");}}byte[] bytes = builder.toString().getBytes();InputStream is = new ByteArrayInputStream(bytes);return is;}/** * * load bulk data from InputStream to MySQL */public int bulkLoadFromInputStream(String loadDataSql,InputStream dataStream) throws SQLException {if(dataStream==null){logger.info("InputStream is null ,No data is imported");return 0;}conn = jdbcTemplate.getDataSource().getConnection();PreparedStatement statement = conn.prepareStatement(loadDataSql);int result = 0;if (statement.isWrapperFor(com.mysql.jdbc.Statement.class)) {com.mysql.jdbc.PreparedStatement mysqlStatement = statement.unwrap(com.mysql.jdbc.PreparedStatement.class);mysqlStatement.setLocalInfileInputStream(dataStream);result = mysqlStatement.executeUpdate();}return result;}public static void main(String[] args) {String testSql = "LOAD DATA LOCAL INFILE ‘sql.csv’ IGNORE INTO TABLE test.test (a,b,c,d,e,f)";InputStream dataStream = getTestDataInputStream();BulkLoadData2MySQL dao = new BulkLoadData2MySQL();try {long beginTime=System.currentTimeMillis();int rows=dao.bulkLoadFromInputStream(testSql, dataStream);long endTime=System.currentTimeMillis();logger.info("importing "+rows+" rows data into mysql and cost "+(endTime-beginTime)+" ms!");} catch (SQLException e) {e.printStackTrace();}System.exit(1);}}

提示:String testSql ="LOAD DATA LOCAL INFILE ‘sql.csv’ IGNORE INTO TABLE test.test (a,b,c,d,e,f)"; 使用setLocalInfileInputStream方法,会直接忽略掉文件名称,而直接将IO流导入到数据库中。参考:%20Performance%20Gems%20Presentation.pdf

原创文章,欢迎转载,转载请注明出处:

我知道我不是一个很好的记录者,但我比任何人都喜欢回首自己来时的路,

Java不写文件,LOAD DATA LOCAL INFILE大批量导入数据到MySQL的

相关文章:

你感兴趣的文章:

标签云: