使用线程进行记录插入的最佳做法?

时间:2015-08-11 13:17:28

标签: java multithreading sqlite jdbc executorservice

我想用超过5亿行填充数据库表,我有以下insert方法:

public void insertRecord(Record rec) throws SQLException, ClassNotFoundException {

    if (this.isTableExists(this.TABLE_NAME)) {

        Connection conn = this.getConnection();
        conn.setAutoCommit(true);
        PreparedStatement ps = conn.prepareStatement("insert into "+this.TABLE_NAME+" ("+this.NODE_ID_COL+", "+this.LAT_COL+", "+this.LNG_COL+", "+this.XML_PATH_COL+") values (?, ?, ?, ?)");

        ps.setString(1, rec.getNodeID());
        ps.setString(2, rec.getLat());
        ps.setString(3, rec.getLng());
        ps.setString(4, rec.getPath());

        ps.addBatch();
        ps.executeBatch();

        ps.close();
        conn.close();

    } else {
        Log.e(TAG, "insertRecord", "table: ["+this.TABLE_NAME+"] does not exist");
    }

}

我的问题是,因为我会插入大量的行:

  1. 我应该在上面发布的方法中使用线程吗?
  2. 这种情况的最佳做法是什么?
  3. 在这种情况下,ExecutorService会产生更好的表现吗?

2 个答案:

答案 0 :(得分:5)

你的方法非常低效。 对于你的每条记录

  1. 获取新连接(如果您有连接池,则不是 问题)
  2. 准备新的PreparedStatement
  3. 创建一批1号
  4. 立即执行批处理
  5. 相反,您应该保留一个PreparedStatement并执行大小为50-100的批次。

    之后,如果您知道自己在做什么,可以考虑使用多线程。多线程并不能让一切变得更快。

答案 1 :(得分:2)

在插入方法中,将记录数组保留为缓冲区。

在您说出100个项目后,创建一个PreparedStatement,然后预约记录呼叫addBatch。添加完所有记录后,请致电executeBatch

这将返回一个受影响记录的数组,每个批次调用的位置。

如果这还不够,那么您应该查看在队列中运行Executors的{​​{1}},其中每个都是一次插入(或者甚至是其中几个插件)。< / p>

问题在于错误处理变得越来越复杂,所以尽量避免错误处理Runnables

同样使用多线程意味着执行是异步的,因此如果您有一个客户端等待响应,您需要仔细同步。