使用 UCanAccess 从大文本文件中插入数据非常慢

Posted

技术标签:

【中文标题】使用 UCanAccess 从大文本文件中插入数据非常慢【英文标题】:Inserting data with UCanAccess from big text files is very slow 【发布时间】:2016-05-24 17:46:00 【问题描述】:

我正在尝试读取每个文件超过 10.000 行的文本文件 .txt,将它们拆分并使用 Java 和 UCanAccess 将数据插入 Access 数据库中。问题是它每次都变得越来越慢(随着数据库变得越来越大)。

现在在读取 7 个文本文件并将它们插入数据库后,该项目需要 20 多分钟才能读取另一个文件。

我试着只做读取,它工作正常,所以问题是实际插入数据库。

注意:这是我第一次将 UCanAccess 与 Java 一起使用,因为我发现 JDBC-ODBC 桥不再可用。任何有关替代解决方案的建议也将不胜感激。

【问题讨论】:

【参考方案1】:

如果您当前的任务只是将大量数据从文本文件直接导入数据库,并且不需要任何复杂的 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

或者,如果您需要手动解析每一行输入,插入一行,并检索新行的 AutoNumber 值,那么代码会更像这样:

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),但请记住,如果应用程序在执行更新。

【讨论】:

谢谢,但我必须拆分文件并在每一行中使用子字符串,因此它需要 sql 查询和字符串拆分。 @Yassine - 如果您使用 SQL(例如,通过 PreparedStatement)一次插入一行,那么您也可以使用 Jackcess 及其 AddRow 方法完成相同的结果。这样你仍然可以避免 UCanAccess/HSQLDB 开销。 是的,我使用 PreparedStatement 插入每一行(基于其前 3 个字符),然后将其与 subString 拆分并将其存储到变量中,我如何使用 Jackcess 和 addRow 方法?注意:我正在使用 AUTO_GENERATED_KEY 返回插入行的主键以在插入后使用它。 addRow 方法有这个选项吗? 非常感谢,我已经回答了这个问题,但仍然有一个问题,我想根据其主键更新一个表,我使用了 UCanAccess 但是当使用 jackcess 打开表时它不会不更新了??如何使用 jackcess 更新它? @YassineBHS - 嗯,性能取决于很多因素,但我刚刚通过 Jackcess 在 Access 数据库中测试了 10,000 行的 upsert,并且始终不到 5 秒。【参考方案2】:

另外,如果您需要使用 slq/ucanaccess,您必须在开始时在连接上调用 setAutocommit(false),并提交每个 200/300 记录。性能将显着提高(约 99%)。

【讨论】:

如何对每条 200/200 条记录进行一次提交? 仅当计数器显示您已插入 200 条记录时,才进行计数并在连接上调用 commit...

以上是关于使用 UCanAccess 从大文本文件中插入数据非常慢的主要内容,如果未能解决你的问题,请参考以下文章

UCanAccess:来自空间的意外令牌

如何使用 UCanAccess 插入行?

如何将 Jaspersoft Studio 与 UCanAccess 一起使用?

使用 UCanAccess 插入 ResultSet 时出现“必须在插入之前设置所有列”错误

在 Ucanaccess 中插入错误

为啥UCanAccess 需要密码而Jackcess 不需要?