【问题标题】:Best practice for using threads for records insertion?使用线程进行记录插入的最佳实践?
【发布时间】:2015-11-03 17:51:41
【问题描述】:

我想填充超过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 是否会产生糟糕的性能?

【问题讨论】:

    标签: java multithreading sqlite jdbc executorservice


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 如果批量大小为 100,并且我想插入 102 条记录,我应该如何处理其余 2 条记录,例如?请指教?
    • 我的意思是,我不知道我想提前插入多少条记录,我该如何处理......请指教
    • 你不需要知道。只需插入您获得的所有记录,至少每 100 次插入执行一次批处理。当项目少于 100 个时,没有什么能阻止您在最后执行较小的批次。
    【解决方案2】:

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

    当你达到 100 个项目后,创建一个 PreparedStatement,然后 foreach 记录调用 addBatch。添加所有记录后,请致电executeBatch

    这将为您返回一个数组,其中包含每个批处理调用的受影响记录。

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

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

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

    【讨论】:

    • 无需为每 100 个项目重新创建准备好的语句。
    • 如果批量大小为 100,并且我想插入 102 条记录,我应该如何处理其余 2 条记录?或者换句话说,如果我不知道我想提前插入多少条记录,我该如何处理这种情况?请指教?
    • 在执行结束时,如果缓冲区不为空,则“刷新”它,在数组上执行一次 foreach 。如果这是一个永远运行的守护进程,请设置一个超时:当缓冲区已满或 n 秒后刷新缓冲区。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多