使用线程进行记录插入的最佳实践?

Best practice for using threads for records insertion?

我想用超过 5 亿行填充数据库 table,我有以下 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 的性能会变差吗?

你的方法效率很低。 对于每条记录,您

  1. 获取一个新的连接(如果你有一个连接池,这不是一个 问题)
  2. 准备新的PreparedStatement
  3. 创建大小为 1 的批次
  4. 立即执行批处理

相反,您应该保留一个 PreparedStatement 并在其上执行大小为 50-100 的批处理。

之后你可以考虑多线程,如果你知道你在做什么。多线程并不是让一切变得更快的魔法。

在您的插入方法中,保留一个记录数组作为缓冲区。

在你达到 100 个项目后,创建一个 PreparedStatement,然后为每个记录调用 addBatch。添加所有记录后调用 executeBatch

这将为您 return 一个数组,其中包含每个批处理调用的受影响记录所在的位置。

如果这还不够,那么是的,您应该查看队列中的 Executors 和 运行 Runnables,它们中的每一个都是一次插入(或者甚至是一批他们中的几个)。

问题是错误处理变得越来越复杂,所以尽量避免它 if you can

同样使用多线程意味着执行是异步的,所以如果你有一个等待响应的客户端,你需要小心同步。