6

我正在尝试将不同的缓冲区大小插入本地 SQLite DB,并发现当缓冲区大小为 10,000 时,插入 10,000,000 行数据需要将近 8 分钟。换句话说,存储所有内容需要 1,000 次写入。

8 分钟存储 10,000,000 似乎有点太长(或者是吗?)

可以优化以下任何一项以提高速度吗?请注意,插入的数据是字符的随机集合。

public int flush() throws SQLException {
    String sql = "insert into datastore values(?,?,?,?);";

    PreparedStatement prep = con.prepareStatement(sql);

    for (DatastoreElement e : content) { // content is 10,000 elements long
        _KVPair kvp = e.getKvp();

        prep.setInt(1, e.getMetaHash());
        prep.setInt(2, kvp.hashCode());
        prep.setString(3, kvp.getKey());
        prep.setString(4, kvp.getValue());

        prep.addBatch();
    }

    int[] updateCounts = prep.executeBatch();

    con.commit();

    return errorsWhileInserting(updateCounts);
}

创建表时,它是通过

    statement.executeUpdate("create table datastore 
               (meta_hash INTEGER," + 
               "kv_hash   INTEGER," + 
               "key TEXT," +
               "value TEXT);");

请问以上任何一个可以进一步优化吗?

4

2 回答 2

13

我对 Java API 有点模糊,但我认为你应该先启动一个事务,否则调用commit()是没有意义的。用conn.setAutoCommit(false). 否则 SQLite 将为每个单独的插入/更新记录日志。这需要同步文件,这将导致速度变慢。

编辑:发问者更新说这已经设置为真。在这种情况下:

那是很多数据。这么长的时间听起来并不在这个世界之外。您可以做的最好的事情是使用不同的缓冲区大小进行测试。在缓冲区抖动太小和虚拟内存因大尺寸而启动之间存在平衡。出于这个原因,您不应该尝试一次将其全部放入一个缓冲区。将插入物分成您自己的批次。

于 2012-08-23T15:36:10.990 回答
2

You are only executing executeBatchonce, which means that all 10 million statements are send to the database in the executeBatch call. This is way too much to handle for a database. You should additionally execute int[] updateCounts = prep.executeBatch(); in your loop let's say all 1000 rows. Just make an if statement which tests on counter % 1000 == 0. Then the database can asynchronously already work on the data you sent.

于 2012-08-23T16:05:14.997 回答