对于MySQL和Java而言,没有文件(即在内存中)的“加载数据”是可能的吗?

我正在优化将~10TB数据导入MySQL数据库。 目前,我可以在当前的笔记本电脑上在大约14分钟内导入2.9GB(+ 0.8GB索引)。 该过程包括读取数据文件(Oracle“.dat”导出),解析数据,将数据写入CSV文件并在其上执行“LOAD DATA LOCAL”sql命令。

是否可以提高导入速度(无需更改硬件)? 有没有办法删除将文件写入文件系统并让MySQL再次读取它的步骤。 是否可以将内存中的数据直接流式传输到MySQL(例如,通过JDBC驱动程序)?

非常感谢,Joerg。

似乎从MySQL Connector / J JDBC驱动程序版本5.1.3开始,您可以使用com.mysql.jdbc.Statement挂接InputStream引用。 setLocalInfileInputStream()方法,在Java代码内部,将内存中格式化的字符串/文本“管道”到“LOAD DATA INFILE”调用。 这意味着您不必从内存中写出并重新读取临时文件。 请参阅:

http://dev.mysql.com/doc/refman/5.1/en/connector-j-reference-implementation-notes.html (页面底部)

这篇文章还概述了这个过程:

http://jeffrick.com/2010/03/23/bulk-insert-into-a-mysql-database

O’reilly制作了一个涵盖MySQL / JDBC性能gem的PDF ,引用了这一点。

还提到了Hadoop (高级Java主题) 的用法 。

希望这一切都有帮助。

干杯

丰富

实际的工作代码很难得到,所以这里有一些:

@Test public void bulkInsert() throws SQLException { try(com.mysql.jdbc.Connection conn = (com.mysql.jdbc.Connection) dao.getDataSource().getConnection()) { conn.setAllowLoadLocalInfile(true); try(com.mysql.jdbc.Statement stmt = (com.mysql.jdbc.Statement) conn.createStatement()) { stmt.execute("create temporary table BasicDbTest_1 (phone integer)"); String data = "8675309\n"; stmt.setLocalInfileInputStream(new ByteArrayInputStream(data.getBytes())); stmt.execute("load data local infile '' into table BasicDbTest_1"); try(ResultSet rs = stmt.executeQuery("select phone from BasicDbTest_1")) { Assert.assertTrue(rs.next()); Assert.assertEquals(rs.getInt(1), 8675309); } } } } 

这可能是你正在寻找的: 源测试4你自己。

在Unix上,如果需要LOAD DATA从管道读取,可以使用以下技术(该示例将/ directory的列表加载到表db1.t1中):

 mkfifo /mysql/data/db1/ls.dat chmod 666 /mysql/data/db1/ls.dat find / -ls & /mysql/data/db1/ls.dat & mysql -e "LOAD DATA INFILE 'ls.dat' INTO TABLE t1" db1 

请注意,您必须在单独的终端上运行生成要加载的数据和mysql命令的命令,或者在后台运行数据生成过程(如上例所示)。 如果不这样做,管道将阻塞,直到mysql进程读取数据。

根据7.2.2.1插入语句速度 ,LOAD DATA INFILE通常比INSERT快20倍。 这可能不是你想要的,但如果它对你很重要,你应该自己测试一下。

根据1.2.2.6加载数据Infile语法

使用LOCAL比让服务器直接访问文件要慢一些,因为文件的内容必须由客户端通过连接发送到服务器。 另一方面,您不需要FILE权限来加载本地文件。

因此,如果您将文件放在服务器上,加载可能会更快。 自己测试4。

这是我的猜测:密钥,索引和/或约束可能会减慢批量数据的负载。 所以下面的内容可能会加快速度。 你最终将不得不处理它们,所以它可能会减慢速度。 自己测试4。

 CREATE TEMPORARY TABLE dataHold {suitable schema, no keys, indices, or constraints} ; LOAD DATA INFILE into dataHold ; INSERT INTO realTable SELECT * FROM dataHold ; DROP TEMPORARY TABLE dataHold