【问题标题】:Insert to database a lot of data with batch insert使用批量插入向数据库插入大量数据
【发布时间】:2014-12-18 08:41:46
【问题描述】:

我创建了一个向 MySql 数据库插入数百万个值的程序。 我读到了批量插入,它将优化我的程序并使其更快,但是当我尝试这样做时,它以相同的方式工作。 我每次将 500 个值都保存在一个列表中,而不是将每个值插入数据库,然后将它们插入一个大循环中,如下所示:

for(int i=0;i<500;i++)
{
   insertData(list.get(i));
}

然后我删除列表中的所有值并再次开始收集 500 个值。 它不应该更好地工作吗?
我的插入代码是:

public void insertToNameTable(String id,String name) throws SQLException
       {
           PreparedStatement ps=null;

            ps= conn.prepareStatement("INSERT INTO NameTable values(?,?,?)",user.getId(),user.getName());


            ps.setString(1,id);
            ps.setString(2,name);
            ps.setBoolean(3,false);
            ps.executeUpdate();

       }

我有一些问题:
1.为什么我批量插入时运行速度不快?
2.每次我应该输入多少个值才能更快?(500,1000,10000)一起输入的值越多越好?
3. 将值插入数据库的方式是最好的方式吗?

【问题讨论】:

  • sql优化比你聪明。你这个微不足道的例子不会欺骗优化器。
  • @ScaryWombat 那么我应该如何以最佳方式将值插入数据库?
  • 发布您的批量插入程序。另外我的 insertData(list.get(i)) 你是说 list.get(i) 返回一个包含 500 个值的列表吗?那么如何插入这 500 个值。您是否使用类似:“插入表(x,y,z)值(1,2,3),(3,4,5),....”
  • @danb list.get(i) 返回给我一个值。列表大小为 500。在我的程序中,我每次在列表中收集 500 个值,而不是在插入后插入,然后将它们一个接一个地插入。我明白这不是正确的方法,但我应该怎么做。我应该每次插入多少个值来优化它?
  • 但你也做同样的事情吗?您创建 500 个不同的插入语句。这不是批量插入

标签: java mysql database sql-insert batch-insert


【解决方案1】:

这是批量插入的有效方式。

Connection connection = new getConnection();
Statement statement = connection.createStatement();
 
for (String query : queries) {
    statement.addBatch(query);
}
statement.executeBatch();
statement.close();
connection.close();

【讨论】:

  • 那是我一直在寻找的,但是我每次应该给他多少查询才能获得最佳优化。 500?1000?10000?以哪种方式效果最好?
  • 您可以根据自己的要求来决定。尽量减少迭代次数
  • 那么你的意思是,如果我可以每次发送 10k 个查询,那会比每次发送 1k 个查询更好?
  • 是的,正是您所了解的。它会减少没有。 i/o 迭代。但是你需要记住的一件事是它不应该抛出堆空间异常。
  • 批量插入与堆空间异常有何关系?我有时会遇到这个异常,但一直不明白为什么。你能解释一下吗?
【解决方案2】:

问题 1 和 2:

网友Neil Coffey前段时间说:

Prepared statements 主要是关于性能的概念是一种误解,尽管它很常见。

另一位发帖人提到,他注意到 Oracle 和 SQL Server 的速度提高了约 20%。我注意到 MySQL 有一个类似的数字。事实证明,解析查询并不是所涉及工作的重要部分。在一个非常繁忙的数据库系统上,查询解析是否会影响整体吞吐量也不清楚:总的来说,它可能只是用尽了 CPU 时间,否则在数据从磁盘返回时会处于空闲状态。

因此,作为使用准备好的语句的一个原因,对 SQL 注入攻击的保护远远超过了性能改进。如果您不担心 SQL 注入攻击,您可能应该...

这是原帖:
PreparedStatements and performance
在我看来,所有答案都值得一读。我认为您希望PreparedStatement 成为某种魔术师,可以显着提高您的插入速度,这就是您对所获得的改进感到失望的原因。

问题 3
使用PreparedStatement 的正确方法是准备一个语句,然后在循环中设置值和更新数据库。这是一个很好的例子:Reusing a PreparedStatement multiple times

【讨论】:

  • 我的经验是 PreparedStatements 显着提高了性能,这是实现系统时非常重要的考虑因素。所选择的基准只是轶事。我担心的是,我们不会延续这样的神话,即准备好的语句不会大大提高性能。对此的基准测试必须考虑到运行复杂查询以及使用不同参数运行类似查询数千或数十万次。每个查询都将被添加到服务器查询缓存中,并填满它的限制。
  • @danb 我同意减少缓存大小和数据库负载,我总是更喜欢PreparedStatement 而不是Statement。我不是 Neil Coffey,我不想为他说话,但请注意:我提供的线程中投票数最高的两个答案有点不同。此外,我在这里的回答得到了赞成和反对。看起来对这个话题的看法各不相同,很难肯定地说谁是对的,谁是错的。正如我所说,我总是使用PreparedStatement,因为我被教导它工作得更快,所以我无法比较这两者。我认为在用户环境中尝试这两种方法将是最好的基准。
  • 两个答案都淡化了使用preparedstatements时性能改进的作用。我担心的是,您的回答将使preparedstatements 不会显着提高性能的暗示永久化。即使没有 SQL 注入,我也会使用它来提高性能。在这里的问题中,我不确定添加了什么价值。而且我已经构建并测试了许多生产系统,并且 PreparedStatements 性能改进是必须的!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-14
  • 1970-01-01
  • 2013-08-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多