在 Java 中更快地将 txt 文件读取到 mySQL 数据库
Read txt-files to mySQL database faster in Java
我正在尝试读取超过 17000 个文件(每个文件包含 100 到 23000 行)并将数据解析到 mysql 数据库中。问题是做的太慢了,不知道瓶颈在哪
private void readFile() {
PreparedStatement prepStatement = null;
String queryInsItem = "INSERT IGNORE INTO item VALUES(?)";
String queryInsUser = "INSERT IGNORE INTO user VALUES(?)";
String queryInsRating = "INSERT IGNORE INTO rating VALUES(?,?,?,?)";
try {
int x = 1;
int itemID = 0;
int userID = 0;
int rating = 0;
java.util.Date date = null;
java.sql.Date sqlDate = null;
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
String line = null;
conn.setAutoCommit(false);
System.out.println("Loading...");
File dir = new File("src/bigdata/training_set/");
File[] directoryListing = dir.listFiles();
if (directoryListing != null) {
for (File itemFile : directoryListing) {
in = new BufferedReader(new FileReader(itemFile));
line = in.readLine();
itemID = Integer.parseInt(line.substring(0, line.length()-1));
userID = 0;
rating = 0;
date = null;
sqlDate = null;
// Add to item table
prepStatement = conn.prepareStatement(queryInsItem);
prepStatement.setInt(1, itemID);
prepStatement.executeUpdate();
conn.commit();
prepStatement.close();
while ((line = in.readLine()) != null) {
// Splits the line to corresponding variables
userID = Integer.parseInt(line.substring(0, line.indexOf(",")));
rating = Integer.parseInt(line.substring(line.indexOf(",")+1, line.lastIndexOf(",")));
date= dateFormat.parse(line.substring(line.lastIndexOf(",")+1, line.length()));
sqlDate = new java.sql.Date(date.getTime());
// Add to user table
prepStatement = conn.prepareStatement(queryInsUser);
prepStatement.setInt(1, userID);
prepStatement.executeUpdate();
conn.commit();
prepStatement.close();
// Add to rating table
prepStatement = conn.prepareStatement(queryInsRating);
prepStatement.setInt(1, userID);
prepStatement.setInt(2, itemID);
prepStatement.setInt(3, rating);
prepStatement.setDate(4, sqlDate);
prepStatement.executeUpdate();
conn.commit();
prepStatement.close();
}
in.close();
System.out.println("File " + x++ +" done.");
}
}
} catch (IOException | ParseException | SQLException e) {e.printStackTrace();}
System.out.println("Done.");
}
我试过先 str.split 行,然后将其更改为 indexOf/lastIndexOf,但没有像 19486077 中提到的那样有明显改善。同一线程中的其他人提到使用线程,但这对我来说是正确的方法吗?
这是原始数据的片段:
5317:
2354291,3,2005-07-05
185150,2,2005-07-05
868399,3,2005-07-05
以上表示:
[item_id]:
[user_id],[rating],[date]
[user_id],[rating],[date]
[user_id],[rating],[date]
- 如果这些表上有
AUTO_INCREMENT
PRIMARY KEY
,请注意 INSERT IGNORE
会疯狂地烧掉 ID。
- "Batch" 插入。如果您收集 100-1000 行,用这些行构建一个 INSERT,然后执行该语句,INSERTion 将 运行 快 10 倍。
- 不要尝试一次批处理 23,000 行,您可能会 运行 遇到一些问题(很难预测是什么问题)。
- 另一方面,如果您可以对这些文件执行
LOAD DATA
,您就可以摆脱所有的解析代码!它 运行 至少与批量插入一样快。
我正在尝试读取超过 17000 个文件(每个文件包含 100 到 23000 行)并将数据解析到 mysql 数据库中。问题是做的太慢了,不知道瓶颈在哪
private void readFile() {
PreparedStatement prepStatement = null;
String queryInsItem = "INSERT IGNORE INTO item VALUES(?)";
String queryInsUser = "INSERT IGNORE INTO user VALUES(?)";
String queryInsRating = "INSERT IGNORE INTO rating VALUES(?,?,?,?)";
try {
int x = 1;
int itemID = 0;
int userID = 0;
int rating = 0;
java.util.Date date = null;
java.sql.Date sqlDate = null;
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
String line = null;
conn.setAutoCommit(false);
System.out.println("Loading...");
File dir = new File("src/bigdata/training_set/");
File[] directoryListing = dir.listFiles();
if (directoryListing != null) {
for (File itemFile : directoryListing) {
in = new BufferedReader(new FileReader(itemFile));
line = in.readLine();
itemID = Integer.parseInt(line.substring(0, line.length()-1));
userID = 0;
rating = 0;
date = null;
sqlDate = null;
// Add to item table
prepStatement = conn.prepareStatement(queryInsItem);
prepStatement.setInt(1, itemID);
prepStatement.executeUpdate();
conn.commit();
prepStatement.close();
while ((line = in.readLine()) != null) {
// Splits the line to corresponding variables
userID = Integer.parseInt(line.substring(0, line.indexOf(",")));
rating = Integer.parseInt(line.substring(line.indexOf(",")+1, line.lastIndexOf(",")));
date= dateFormat.parse(line.substring(line.lastIndexOf(",")+1, line.length()));
sqlDate = new java.sql.Date(date.getTime());
// Add to user table
prepStatement = conn.prepareStatement(queryInsUser);
prepStatement.setInt(1, userID);
prepStatement.executeUpdate();
conn.commit();
prepStatement.close();
// Add to rating table
prepStatement = conn.prepareStatement(queryInsRating);
prepStatement.setInt(1, userID);
prepStatement.setInt(2, itemID);
prepStatement.setInt(3, rating);
prepStatement.setDate(4, sqlDate);
prepStatement.executeUpdate();
conn.commit();
prepStatement.close();
}
in.close();
System.out.println("File " + x++ +" done.");
}
}
} catch (IOException | ParseException | SQLException e) {e.printStackTrace();}
System.out.println("Done.");
}
我试过先 str.split 行,然后将其更改为 indexOf/lastIndexOf,但没有像 19486077 中提到的那样有明显改善。同一线程中的其他人提到使用线程,但这对我来说是正确的方法吗?
这是原始数据的片段:
5317:
2354291,3,2005-07-05
185150,2,2005-07-05
868399,3,2005-07-05
以上表示:
[item_id]:
[user_id],[rating],[date]
[user_id],[rating],[date]
[user_id],[rating],[date]
- 如果这些表上有
AUTO_INCREMENT
PRIMARY KEY
,请注意INSERT IGNORE
会疯狂地烧掉 ID。 - "Batch" 插入。如果您收集 100-1000 行,用这些行构建一个 INSERT,然后执行该语句,INSERTion 将 运行 快 10 倍。
- 不要尝试一次批处理 23,000 行,您可能会 运行 遇到一些问题(很难预测是什么问题)。
- 另一方面,如果您可以对这些文件执行
LOAD DATA
,您就可以摆脱所有的解析代码!它 运行 至少与批量插入一样快。