我正在使用不同的缓冲区大小插入到本地SQLite DB中,并且发现当缓冲区大小为10,000时,插入10,000,000行数据需要将近8分钟。换句话说,它需要1,000次写入来存储所有内容。
存储10,000,000的8分钟似乎有点太长(或者是吗?)
可以对以下任何一项进行优化以提高速度吗?请注意,插入的数据是随机的字符集。
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);");
可以对上述任何一项进行进一步优化吗?
答案 0 :(得分:13)
我对Java API有些模糊,但我认为你应该先启动一个事务,否则调用commit()
是毫无意义的。使用conn.setAutoCommit(false)
执行此操作。否则,SQLite将为每个插入/更新进行日志记录。这需要同步文件,这将导致缓慢。
编辑:提问者更新说这已经设定了。在那种情况下:
这是很多数据。那段时间听起来并不是这个世界。您可以做的最好的事情是使用不同的缓冲区大小进行测试。它们之间的缓冲抖动太小而虚拟内存对于大尺寸而言是平衡的。因此,您不应该尝试将其全部放入一个缓冲区中。将插入物拆分成您自己的批次。
答案 1 :(得分:0)
您只执行executeBatch
一次,这意味着所有1000万条语句都会在executeBatch
调用中发送到数据库。这对于数据库来说太过分了。
你应该在你的循环中另外执行int[] updateCounts = prep.executeBatch();
让我们说1000行。只需创建一个if语句,对counter % 1000 == 0
进行测试。然后,数据库可以异步处理您发送的数据。