【问题标题】:Optimization INSERT with huge amount of data使用大量数据优化 INSERT
【发布时间】:2013-12-12 19:02:16
【问题描述】:

我在一个简单的 Java 控制台应用程序中使用 PreparedStatementInputStream 中加载大量数据。

这是代码:

public void readStopTimes(CSVReader reader) throws IOException, SQLException {
        String insertSql = "INSERT INTO stop_times VALUES (null, ?, ?, ?, ?, ?)";
        PreparedStatement statement = db.prepareStatement(insertSql);
        String [] nextLine;
        long i = 0;
        Chronometer chronometer = new Chronometer();
        while ((nextLine = reader.readNext()) != null) {
            if(i++ != 0) {
                statement.setString(1, nextLine[0]);
                if(nextLine[1].isEmpty())
                    statement.setNull(2, Types.TIME);
                else
                    statement.setTime(2, Time.valueOf(nextLine[1]));
                if(nextLine[2].isEmpty())
                    statement.setNull(3, Types.TIME);
                else
                    statement.setTime(3, Time.valueOf(nextLine[2]));
                statement.setString(4, nextLine[3]);
                statement.setInt(5, Integer.parseInt(nextLine[4]));
                statement.addBatch();
            }
            if(i++ % 1000 == 0) {
                statement.executeBatch();
            }
            if(chronometer.count() > 5000) {
                chronometer.restart();
                log.debug("Analyzed {} rows", i);
            }
        }
        statement.executeBatch();
        db.commit();
    }

每 1000 次插入执行批处理,每 5 秒打印一次日志。

从日志中可以看出,该算法在开始时运行得非常快,在前 25 秒内总共计算了超过 400 万行,然后它变慢了,在 5 秒内只添加了 2 行到批次。

我需要插入超过 500 万行,你有更快的替代方案吗?

【问题讨论】:

  • 我不知道答案,但为了测试:你能在statement.executeBatch();之后添加statement = db.prepareStatement(insertSql);吗?

标签: java mysql performance


【解决方案1】:
  • 在 mysql 中禁用查询缓存
  • innodb_flush_log_at_trx_commit = 2 或者如果你能确保你的 mysql 不会崩溃而不是让它 innodb_flush_log_at_trx_commit = 0
  • 如果启用了复制,则通过执行sync_binlog = 0 禁用bin 日志的同步

您可以尝试通过Load data infile . . . . . 命令直接将CSV文件放入MySql,速度非常快。

【讨论】:

  • 唯一有效的解决方案是Load data infile,最终用java预解析文件。
【解决方案2】:

尝试在 statement.executeBatch(); 之后提交而不是在最后。这应该允许在您继续操作时刷新插入,因为 mysql 会密切关注您的插入,以便在必要时将它们全部回滚。

【讨论】:

    【解决方案3】:

    尝试以多个批次而不是单个批次添加数据。在每批之后提交并跟踪处理过的数据。或者您可以使用临时表将数据添加到表中,一旦完成,重命名表,以防失败,重新启动或从保存点开始。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多