对于数据库MySQL 我想尽快插入行,因为它可以完成。 插入将以多线程方式执行。让它接近200个线程。
我有两种方法可以做到:
1)使用简单的Insert命令,每个Insert都将被包装到事务中。
有一个很好的MySQL解决方案批量插入 (INSERT INTO t()VALUES(),(),()...)但不能使用它,因为每一行在事务方面必须是独立的。换句话说,如果操作中出现一些问题,我想只回滚一个插入的行,而不是批处理中的所有行。
在这里,我们可以采用第二种方式:
2)单线程可以使用伪数据进行批量插入,除自动增量ID外,完全为空行。这种插入物的工作速度非常快,与单个插入物相比,我们甚至可以忽略此时间(约40纳秒/行)。 批量插入后,客户端可以获得LAST_INSERT_ID和ROW_COUNT,即插入ID的“范围”。下一步是使用我们想要从之前的'范围'获得的ID对我们想要插入的数据进行更新。更新将以多线程方式执行。结果将是相同的。
现在我想问:哪种方式会更快 - 单次插入或批量插入+更新。
表中有一些索引。
答案 0 :(得分:1)
以上都不是。
您应该进行批量插入。如果发生BatchUpdateException
,您可以捕获它并找出哪些插入失败。但是,您仍然可以提交到目前为止所提供的内容,然后从批处理失败的位置开始继续(这取决于驱动程序,某些驱动程序将执行所有语句并通知您哪些语句失败)。
答案 1 :(得分:1)
答案取决于错误的主要原因,并且您想要对失败的交易做什么,INSERT IGNORE
可能就足够了:
INSERT IGNORE . . .
这将忽略批处理中的错误但插入有效数据。如果你想捕捉错误并对它们做些什么,这很棘手。
如果错误是由重复键(唯一键或主键)引起的,则ON DUPLICATE KEY UPDATE
可能是最佳解决方案。
答案 2 :(得分:1)
计划A:
如果存在辅助INDEXes
,则批量插入+大量更新可能会更慢,因为它需要插入索引行,然后更改它们。 OTOH,因为二级索引操作是在“更改缓冲区”中完成的,因此延迟了,您可能不会立即注意到开销。
不要使用200个线程来执行多线程插入或更新。对于5.7,64可能是限制; 5.6可能是48. YMMV。这些数字来自于Oracle吹嘘他们如何改进MySQL的多线程方面。除了这些数字之外,吞吐量平坦且延迟也在不断增加。您应该尝试 情况,而不要相信这些数字。
B计划:
如果失败的行很少见,那就要乐观。批量INSERTs
,例如,一次64个。如果发生故障,则在8批8中重做它们。如果其中任何一个失败,则一次退化为一个。我不知道什么样的模式是最佳的。 (64-8-1或64-16-4-1或25-5-1或......)无论如何,它取决于您的故障频率和要插入的行数。
然而,我会传授这一点建议......超过100个线程,你很好地“收益递减”,所以不要打扰可能失败的大批量。我测得100 /批量约为最大速度的90%。
另一个提示(适用于任何计划):
innodb_flush_log_at_trx_commit = 2
sync_binlog = 0
注意:这些有助于提高速度(可能非常显着),但在电源故障时可能会丢失数据。