“INSERT ... ON DUPLICATE KEY UPDATE”的性能与“UPDATE”的比较

ant*_*tak 3 mysql

99% 的情况下,单个就足够了,但不到 0.01% 的情况下,我需要在同一键上UPDATE跟进。INSERT这可以写成一个单一的INSERT ... ON DUPLICATE KEY UPDATE,但就性能而言,我应该吗?

问题基本上是INSERT ... ON DUPLICATE KEY UPDATEs 是否预计比UPDATEMySQL 中的 s 慢。

一些代码来演示:

代码使用UPDATE

UPDATE foo SET seq = @new_seq WHERE id = X AND seq = @prev_seq;

IF rows_changed = 0 THEN
    INSERT INTO foo (id, seq) VALUES (X, @new_seq)
    IF <duplicate key error> THEN
        -- handle collusion
    END IF
END IF
Run Code Online (Sandbox Code Playgroud)

代码使用INSERT ... ON DUPLICATE KEY UPDATE

INSERT INTO foo (id, seq) VALUES (X, @new_seq)
    ON DUPLICATE KEY UPDATE seq = IF(seq = @prev_seq, VALUES(seq), seq)

IF rows_changed = 0 THEN
    -- handle collusion
END IF
Run Code Online (Sandbox Code Playgroud)

wal*_*ter 6

强烈建议您自己对它们进行基准测试。

这很容易做到,而且更有说服力。


从理论上讲,我认为这不会INSERT ... ON DUPLICATE KEY UPDATE拖累你。

情况1:更新没有索引的表

在这种情况下,该UPDATE操作将锁定该表中的所有记录。但INSERT操作只锁定一个间隙(Insert Intention Lock)和插入的记录。

由于您在此处使用INSERT ... ON DUPLICATE KEY UPDATE,因此您更有可能正在使用索引更新表。

情况2:使用索引更新表

假设您正在使用主键更新表。和UPDATEINSERT将支付相同的成本来查找 B+ 树中的特定记录。对于 也是一样INSERT ... ON DUPLICATE KEY UPDATE。所以没有理由INSERT ... ON DUPLICATE KEY UPDATE会慢很多。

此外,INSERT ... ON DUPLICATE KEY UPDATE如果发现重复键,则不会添加插入意向锁。它只会IX在表上加锁,并X在特定记录上加锁,就像这样UPDATE做一样。

  • 案例2听起来很合理,让我有信心继续下去。尽管如此,我还是进行了基准测试,批处理 10,000 个更新的时间大约为 3 秒,因此没有明显差异。案例 1 似乎是在比较语义上不同的事物。 (3认同)