[英]Parse huge CSV file
我有一個巨大的 CSV 文件
經過研究,我找到了這個解決方案
//configure input format using
CsvParserSettings settings = new CsvParserSettings();
//get an interator
CsvParser parser = new CsvParser(settings);
Iterator<String[]> it = parser.iterate(new File("/path/to/your.csv"), "UTF-8").iterator();
//connect to the database and create an insert statement
Connection connection = getYourDatabaseConnectionSomehow();
final int COLUMN_COUNT = 2;
PreparedStatement statement = connection.prepareStatement("INSERT INTO some_table(column1, column2) VALUES (?,?)");
//run batch inserts of 1000 rows per batch
int batchSize = 0;
while (it.hasNext()) {
//get next row from parser and set values in your statement
String[] row = it.next();
//validation
if (!row[0].matches(some regex)){
badDataList.add(row);
conitunue;
}
for(int i = 0; i < COLUMN_COUNT; i++){
if(i < row.length){
statement.setObject(i + 1, row[i]);
} else { //row in input is shorter than COLUMN_COUNT
statement.setObject(i + 1, null);
}
}
//add the values to the batch
statement.addBatch();
batchSize++;
//once 1000 rows made into the batch, execute it
if (batchSize == 1000) {
statement.executeBatch();
batchSize = 0;
}
}
// the last batch probably won't have 1000 rows.
if (batchSize > 0) {
statement.executeBatch();
}
// or use jook#loadArrays
context.loadInto("book")
.batchAfter(500)
.loadArrays(new ArrayList <String[]>)
但是,它仍然太慢,因為它在同一個線程中執行。 有沒有辦法通過多線程更快地做到這一點?
不要逐個迭代記錄,而是使用諸如LOAD DATA INFILE
之類的命令批量導入數據:
JDBC:使用流從遠程 MySQL 數據庫導出/導入 CSV 原始數據(SELECT INTO OUTFILE / LOAD DATA INFILE)
注意:正如@XtremeBaumer 所說,每個數據庫供應商都有自己的用於從文件批量導入的命令。
可以使用不同的策略進行驗證,例如,如果可以使用 SQL 進行驗證,則可以將數據導入臨時表,然后選擇有效數據到目標表。
或者,您可以使用 Java 代碼驗證數據,然后對已驗證的數據使用批量導入,而不是一一導入。
首先你應該關閉語句和連接,使用 try-with.-resources.. 然后檢查(自動)提交事務性。
connection.setAutoCommit(true);
如果數據庫正在使用中,則在同一類別中將是表上的數據庫鎖。
正則表達式很慢,而是:
if (!row[0].matches(some regex)) {
做
private static Pattern SKIP_PATTERN = Pattern.compile(some regex);
...
if (SKIP_PATTERN.matcher(row[0]).matches()) { continue; }
如果有一個像整數 ID 這樣的運行數字,通過將數字保持在一個long
的( statement.setLong(...)
)中,批處理可能會更好。 如果該值是一個短的有限域,而不是 1000 個不同的 String 實例,則可以使用 string 到同一字符串的標識映射。 不確定這兩項措施是否有幫助。
多線程似乎很可疑,應該是最后的資源。 您可以寫入解析 CSV 的隊列,同時將其消耗到數據庫中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.