使用 UCanAccess 从大文本文件插入数据非常慢
Inserting data with UCanAccess from big text files is very slow
我正在尝试读取每个文件超过 10.000 行的文本文件 .txt,拆分它们并使用 Java 和 UCanAccess 将数据插入到 Access 数据库中。问题是它每次都变得越来越慢(随着数据库变大)。
现在在读取 7 个文本文件并将它们插入数据库后,项目需要 20 多分钟才能读取另一个文件。
我试着只读取数据,它工作正常,所以问题是实际插入数据库。
N.B:这是我第一次使用UCanAccess 和Java,因为我发现JDBC-ODBC Bridge 不再可用。对于替代解决方案的任何建议也将不胜感激。
如果您当前的任务只是将大量数据从文本文件直接导入数据库,并且不需要任何复杂的 SQL 操作,那么您可以考虑使用 Jackcess API 直接。例如,要导入 CSV 文件,您可以这样做:
String csvFileSpec = "C:/Users/Gord/Desktop/BookData.csv";
String dbFileSpec = "C:/Users/Public/JackcessTest.accdb";
String tableName = "Book";
try (Database db = new DatabaseBuilder()
.setFile(new File(dbFileSpec))
.setAutoSync(false)
.open()) {
new ImportUtil.Builder(db, tableName)
.setDelimiter(",")
.setUseExistingTable(true)
.setHeader(false)
.importFile(new File(csvFileSpec));
// this is a try-with-resources block,
// so db.close() happens automatically
}
或者,如果您需要手动解析每一行输入,插入一行,并检索新行的自动编号值,那么代码将更像这样:
String dbFileSpec = "C:/Users/Public/JackcessTest.accdb";
String tableName = "Book";
try (Database db = new DatabaseBuilder()
.setFile(new File(dbFileSpec))
.setAutoSync(false)
.open()) {
// sample data (e.g., from parsing of an input line)
String title = "So, Anyway";
String author = "Cleese, John";
Table tbl = db.getTable(tableName);
Object[] rowData = tbl.addRow(Column.AUTO_NUMBER, title, author);
int newId = (int)rowData[0]; // retrieve generated AutoNumber
System.out.printf("row inserted with ID = %d%n", newId);
// this is a try-with-resources block,
// so db.close() happens automatically
}
要根据主键更新现有行,代码为
Table tbl = db.getTable(tableName);
Row row = CursorBuilder.findRowByPrimaryKey(tbl, 3); // i.e., ID = 3
if (row != null) {
// Note: column names are case-sensitive
row.put("Title", "The New Title For This Book");
tbl.updateRow(row);
}
请注意,为了获得最大速度,我在打开数据库时使用了 .setAutoSync(false)
,但请记住,如果应用程序在执行更新时异常终止。
此外,如果您需要使用slq/ucanaccess,您必须在开始时对连接调用setAutocommit(false),并且每200/300 条记录执行一次提交。性能将显着提高(约 99%)。
我正在尝试读取每个文件超过 10.000 行的文本文件 .txt,拆分它们并使用 Java 和 UCanAccess 将数据插入到 Access 数据库中。问题是它每次都变得越来越慢(随着数据库变大)。
现在在读取 7 个文本文件并将它们插入数据库后,项目需要 20 多分钟才能读取另一个文件。
我试着只读取数据,它工作正常,所以问题是实际插入数据库。
N.B:这是我第一次使用UCanAccess 和Java,因为我发现JDBC-ODBC Bridge 不再可用。对于替代解决方案的任何建议也将不胜感激。
如果您当前的任务只是将大量数据从文本文件直接导入数据库,并且不需要任何复杂的 SQL 操作,那么您可以考虑使用 Jackcess API 直接。例如,要导入 CSV 文件,您可以这样做:
String csvFileSpec = "C:/Users/Gord/Desktop/BookData.csv";
String dbFileSpec = "C:/Users/Public/JackcessTest.accdb";
String tableName = "Book";
try (Database db = new DatabaseBuilder()
.setFile(new File(dbFileSpec))
.setAutoSync(false)
.open()) {
new ImportUtil.Builder(db, tableName)
.setDelimiter(",")
.setUseExistingTable(true)
.setHeader(false)
.importFile(new File(csvFileSpec));
// this is a try-with-resources block,
// so db.close() happens automatically
}
或者,如果您需要手动解析每一行输入,插入一行,并检索新行的自动编号值,那么代码将更像这样:
String dbFileSpec = "C:/Users/Public/JackcessTest.accdb";
String tableName = "Book";
try (Database db = new DatabaseBuilder()
.setFile(new File(dbFileSpec))
.setAutoSync(false)
.open()) {
// sample data (e.g., from parsing of an input line)
String title = "So, Anyway";
String author = "Cleese, John";
Table tbl = db.getTable(tableName);
Object[] rowData = tbl.addRow(Column.AUTO_NUMBER, title, author);
int newId = (int)rowData[0]; // retrieve generated AutoNumber
System.out.printf("row inserted with ID = %d%n", newId);
// this is a try-with-resources block,
// so db.close() happens automatically
}
要根据主键更新现有行,代码为
Table tbl = db.getTable(tableName);
Row row = CursorBuilder.findRowByPrimaryKey(tbl, 3); // i.e., ID = 3
if (row != null) {
// Note: column names are case-sensitive
row.put("Title", "The New Title For This Book");
tbl.updateRow(row);
}
请注意,为了获得最大速度,我在打开数据库时使用了 .setAutoSync(false)
,但请记住,如果应用程序在执行更新时异常终止。
此外,如果您需要使用slq/ucanaccess,您必须在开始时对连接调用setAutocommit(false),并且每200/300 条记录执行一次提交。性能将显着提高(约 99%)。