输入集:数千(> 10000)个csv文件,每个文件包含> 50000个条目。 输出:将这些数据存储在mysql db。
中采取的方法: 读取每个文件并将数据存储到数据库中。以下是相同的代码段。请建议这种方法是否合适。
PreparedStatement pstmt2 = null;
try
{
pstmt1 = con.prepareStatement(sqlQuery);
result = pstmt1.executeUpdate();
con.setAutoCommit(false);
sqlQuery = "insert into "
+ tableName
+ " (x,y,z,a,b,c) values(?,?,?,?,?,?)";
pstmt2 = con.prepareStatement(sqlQuery);
Path file = Paths.get(filename);
lines = Files.lines(file, StandardCharsets.UTF_8);
final int batchsz = 5000;
for (String line : (Iterable<String>) lines::iterator) {
pstmt2.setString(1, "somevalue");
pstmt2.setString(2, "somevalue");
pstmt2.setString(3, "somevalue");
pstmt2.setString(4, "somevalue");
pstmt2.setString(5, "somevalue");
pstmt2.setString(6, "somevalue");
pstmt2.addBatch();
if (++linecnt % batchsz == 0) {
pstmt2.executeBatch();
}
}
int batchResult[] = pstmt2.executeBatch();
pstmt2.close();
con.commit();
} catch (BatchUpdateException e) {
log.error(Utility.dumpExceptionMessage(e));
} catch (IOException ioe) {
log.error(Utility.dumpExceptionMessage(ioe));
} catch (SQLException e) {
log.error(Utility.dumpExceptionMessage(e));
} finally {
lines.close();
try {
pstmt1.close();
pstmt2.close();
} catch (SQLException e) {
Utility.dumpExceptionMessage(e);
}
}
答案 0 :(得分:2)
我过去曾经使用过LOAD DATA INFILE这样的情况。
LOAD DATA INFILE语句将文本文件中的行读取到 桌子以非常高的速度。 LOAD DATA INFILE是对的补充 SELECT ... INTO OUTFILE。 (见第14.2.9.1节,“SELECT ... INTO 语法“。)要将表中的数据写入文件,请使用SELECT ... INTO OUTFILE。要将文件读回表中,请使用LOAD DATA INFILE。该 FIELDS和LINES子句的语法对于两者都是相同的 声明。这两个子句都是可选的,但FIELDS必须在LINES之前 如果两者都被指定。
IGNORE数字LINES选项可用于忽略文件开头的行。例如,您可以使用IGNORE 1 LINES跳过包含列名称的初始标题行:
LOAD DATA INFILE'/tmp/test.txt'INTO TABLE test IGNORE 1 LINES;
答案 1 :(得分:1)
正如@Ridrigo已经指出的那样,LOAD DATA INFILE是要走的路。根本不需要Java。
如果您的CSV格式不能直接插入数据库,您的Java代码可以重新绘制图片。使用它来重新组织/转换CSV并将其另存为另一个CSV文件,而不是将其写入数据库。
您还可以使用Java代码遍历包含CSV的文件夹,然后执行
的系统命令Runtime r = Runtime.getRuntime();
Process p = r.exec("mysql -p password -u user database -e 'LOAD DATA INFILE ....");
您会发现这比为CSV文件的每一行运行单独的SQL查询要快得多。