哪个更快?插入或更新?

哪个更快?插入或更新?

问题描述:

对于数据库MySQL 我想尽快插入行,因为它可以做到。 插入将以多线程方式执行。让它接近200线程。哪个更快?插入或更新?

有两种方法可以做到这一点,因为我想做的事:

1)使用简单插入命令,各插入将被包装成交易。 (INSERT INTO t()VALUES(),(),()...)但是它不能被使用,因为每一行都必须是独立的交易条款。换句话说,如果操作出现一些问题,我想只回滚一个插入的行,但不是批次中的所有行。

在这里,我们可以接近第二种方式:

2)单个线程可以用假数据,除了自动递增的ID完全空行做批量插入。这插入工作如此之快,我们甚至可以忽略这一次(大约40纳秒/行)与单个插入比较。 批量插入客户端后可以获得LAST_INSERT_ID和ROW_COUNT,即插入ID的'范围'。下一步是使用我们可以从之前的'范围'得到的ID之前用我们想要插入的数据进行更新。更新将以多线程方式执行。结果将是相同的。

现在我想问:哪种方式会更快 - 单次插入或批量插入+更新。

表中有一些索引。

以上都不是。

你应该做批量插入。如果出现BatchUpdateException,您可以捕获它并找出哪些插入失败。但是,您仍然可以执行您目前为止的操作,然后继续从批处理失败的角度(这是驱动程序相关的,一些驱动程序将执行所有语句并通知您哪些失败)。

+0

问题不在于“批量插入”或“插入或更新”。商业智能 - 完全不适合,我之前已经提到过它。当我写这篇文章时,我想要大胆一些,但是我会记住严格的版主和其他人。但无论如何,非常感谢你 – user2602807

+1

这是一个认真的答案,但你似乎并不喜欢我花时间来帮助**你**与**你的**问题。即使它不是你想要的,你也可能没有评论和忽略它。现在寻找黑名单功能... – john16384

+0

每个人都花时间回答或询问。 – user2602807

答案取决于错误的主要原因,whatyou希望与失败的交易做,INSERT IGNORE可能就足够了:

INSERT IGNORE . . . 

这将忽略该批次的错误,但插入的有效数据。这很棘手,如果你想捕捉错误并对它们做些什么。

如果错误是由重复密钥(无论是唯一的还是主要的)引起的,那么ON DUPLICATE KEY UPDATE可能是最好的解决方案。

+0

忽略错误并不适合我的情况,而且我之前已经提到了每一行的独立性。没有批次用于真实数据,只批量为假批量。 – user2602807

计划A:

如果有二次INDEXes,则批量插入+大量的更新可能是慢,因为它需要插入索引行,然后对其进行更改。 OTOH,由于二级索引操作是在“更改缓冲区”中完成的,因此延迟了,您可能不会立即注意到开销。

不要使用200个线程来执行多线程插入或更新。对于5.7,64可能是限制;对于5.6可能是48. YMMV。这些数据来自Oracle吹嘘他们如何改进MySQL的多线程方面。除了这些数字之外,平均吞吐量和延迟都在整个屋顶出现。你应该试试你的的情况,不信任这些数字。

B计划:

如果失败的行很少,那么应该乐观。批次INSERTs,例如每次64个。如果发生故障,请分8次重做。如果其中任何一次失败,则一次退化为一次。我不知道什么样的模式是最佳的。 (64-8-1或64-16-4-1或25-5-1或...)无论如何,这取决于您的失败频率和要插入的行数。

但是,我会传授这一点建议......超过100个线程,你很好地陷入“收益递减”,所以不要担心可能会失败的大批量。我已经测量过100次/批量是最大速度的90%左右。

另一个技巧(任何计划):

innodb_flush_log_at_trx_commit = 2 
sync_binlog = 0 

警告:这些帮助的速度(也许显著),但运行的数据丢失在发生电源故障的风险。

+0

我对48和64个线程的限制感到非常惊讶。我在哪里可以找到证明?我如何为MySQL 5.1和5.5版本定义实际值?我已经认为5.6,5.7更好,但无论如何 – user2602807

+1

5.0更像是8个线程;我不记得5.1和5.5。有一段时间,Percona的XtraDB插件是最好的。这些数据来自MySQL会议,开发人员吹嘘他们所取得的重大进展。或者来自Facebook的工程师,他们严厉地强调MySQL。无论如何,200很可能超过100个。 –