【问题标题】:MySql UPDATE optimization?MySql UPDATE 优化?
【发布时间】:2011-01-13 22:39:39
【问题描述】:

假设我有一个包含两列 A 和 B 的表。A 列有索引,但 B 列没有索引。 我想发出几百万个查询,例如:

UPDATE t1 SET b=b1 WHERE a=a1;
UPDATE t1 SET b=b2 WHERE a=a2;
....

有 1 到 100,000 行对应于 a 的每个唯一值。平均来说是 100 左右。

对于每个更新语句,平均 60% 的行不会更改,因为这些行 b 已经具有所需的值。对于 30% 的更新,不会更改任何匹配的行。

使用这样的语句有意义吗?

UPDATE t1 SET b=b1 WHERE a=a1 AND b<>b1;

它会通过消除不必要的磁盘写回来加速这个过程,还是 Mysql 5 足够聪明,可以识别出没有任何变化并且不需要写回磁盘?

【问题讨论】:

    标签: mysql database performance


    【解决方案1】:

    在任何一种情况下,MySQL 都必须读取行内容(无论是在磁盘上还是在缓存/缓冲池中)。无论哪种情况,MySQL 都会使用您在a 上的索引作为起点。在任何一种情况下,如果该行已经具有b 的目标值,MySQL 将不会更新该行。因此,我看不到 MySQL 会从拥有b&lt;&gt;b1 子句中受益的任何方式。

    可以说,根据工作负载和数据集,如果您将a 上的索引更改为a 上的复合索引和b(按此顺序)。在这种情况下,它不必访问磁盘(或检查缓存/缓冲池)来查找具体需要更新的行(即您可以利用您提到的 30% 和 60% )。话虽如此,现在您的索引将需要更新 b 上的每个更新,因此有成本,尽管我怀疑这种权衡可能是值得的。

    【讨论】:

      【解决方案2】:

      您应该添加额外的过滤器。 Mysql 足够聪明,不会更新相同的值,但最好消除此检查。您可以通过查看查询“影响”了多少行来确认这一点。

      【讨论】:

        【解决方案3】:

        我一直在考虑使用 CASE 将多个更新组合成一个更新

        update t1
        set b=
          case a
            when a=a1 then b1
            when a=a2 then b2
            when a=a3 then b3 ...
          end;
        

        希望这有用,如果速度太慢,请附上解释

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-08-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-03-07
          • 2013-10-25
          相关资源
          最近更新 更多