在 MySQL 中插入 5 万条记录
Posted
技术标签:
【中文标题】在 MySQL 中插入 5 万条记录【英文标题】:Insert 50 thousand record in MySQL 【发布时间】:2009-09-18 12:11:44 【问题描述】:我想通过一个用 Java 编写的 Web 服务将 50 000 条记录插入 mysql,但只插入了 20 000 条记录。
我认为我的 sql 中没有大小(记录数)限制。
有什么东西可以让我一次插入/选择 50k 条记录(批量)
【问题讨论】:
请通过添加代码的sn-p来完成您的问题。 一次插入一千个,它甚至可能会更高效。 【参考方案1】:拆分成多个事务,不要连续插入 50k 条记录。我认为这就是问题所在。
编辑:因为它是一个网络服务,可能在传输过程中连接中断。请确保不是这种情况=)。
回答 OP 的评论: 而不是
INSERT (......) INTO table (...)
INSERT (......) INTO table (...)
INSERT (......) INTO table (...)
INSERT (......) INTO table (...)
... 49 990 INSERT later
INSERT (......) INTO table (...)
INSERT (......) INTO table (...)
INSERT (......) INTO table (...)
INSERT (......) INTO table (...)
做
BEGIN TRANSACTION my_beloved_transaction
INSERT (......) INTO table (...)
INSERT (......) INTO table (...)
... 2k INSERT later
INSERT (......) INTO table (...)
INSERT (......) INTO table (...)
COMMIT TRANSACTION my_beloved_transaction
BEGIN TRANSACTION my_beloved_transaction
INSERT (......) INTO table (...)
INSERT (......) INTO table (...)
... 2k INSERT later
INSERT (......) INTO table (...)
INSERT (......) INTO table (...)
COMMIT TRANSACTION my_beloved_transaction
等等……
【讨论】:
拆分成多个事务,不要连续插入50k条记录---请解释.. 上帝禁止你用谷歌搜索或搜索堆栈溢出的“sql 事务”。【参考方案2】:我不知道您是如何进行插入的,但您可以循环遍历要插入的内容,然后在每 5000 条记录中,使用 Web 服务插入该批次,然后继续下一批,直到你完成。因此,在本例中,您将对 Web 服务进行 10 次调用,每次调用 5000 条记录。
检查 MySQL 事务的使用,以便在批处理出现任何问题时停止此操作(我自己没有在 MySQL 中使用过这些事务,所以我无法帮助解决这部分问题。)
【讨论】:
【参考方案3】:除非这是一个快速而肮脏的概念证明,否则它应该是一个网络服务。 Web 服务只是外部接口。
您应该将此视为 MySQL/JDBC 问题。如果您需要全部或非插入成功,则需要一个长时间运行的事务,可能带有批量插入。
Web 服务问题应该是单独的 - 您可能会担心客户端是否可以等待插入完成以确认使其同步,或者您是否需要回调。这是 Web 服务设计的问题。将两者解耦并分开处理。
【讨论】:
【参考方案4】:您是否在查询失败时检查错误。您是否有可能遇到服务器的 max_allowed_packet 大小?我不确定不在事务中的批量插入的行为是什么,但它可能会导致大型 SQL 语句出现异常错误:
http://dev.mysql.com/doc/refman/5.1/en/packet-too-large.html
【讨论】:
【参考方案5】:可能是内存问题?尝试使用带有 addBatch() 命令的 PreparedStatement 并批量提交:
PreparedStatement stmt = prepareStatement(...);
int count = 0;
for (MyObject eachData : dataList)
stmt.setObject(1, eachData.getDate());
stmt.setBigDecimal(2, eachData.getValue1());
stmt.setBigDecimal(3, eachData.getValue2());
stmt.addBatch();
if (count++ > 100) // flush the batch periodically, so batches don't get too large
int[] ints = stmt.executeBatch();
log.log(Level.INFO, "Inserted " + ints.length + " new records");
stmt.clearBatch();
count = 0;
final int[] ints = stmt.executeBatch();
log.log(Level.INFO, "Inserted " + ints.length + " new records");
【讨论】:
【参考方案6】:可能是批量/批量插入/更新过程的实现导致了这些限制。如果每行中有更多数据,那么您会发现插入的行更少,它会死掉。
尝试使用多个批量/批量插入一次做一个子集。
【讨论】:
【参考方案7】:你可以使用mysql的load infile命令。首先将所有数据写入一个文本文件,然后使用 load infile 命令加载到数据库中,这将花费更少的时间和插入大记录的最佳方法。
【讨论】:
【参考方案8】:当您在事务中运行时,数据必须保留一个回滚段,以防事务失败。磁盘和内存与此日志相关联,因此必须设置限制。我会检查默认值,看看您是否超过了一个或两个。
提交较小批次的好处是回滚段每次都重置为零。这就是为什么将其分成更小的批次会有所帮助。
【讨论】:
以上是关于在 MySQL 中插入 5 万条记录的主要内容,如果未能解决你的问题,请参考以下文章