单个事务中的多个UPDATE与一个带有大WHERE子句的UPDATE

时间:2014-09-08 13:19:14

标签: mysql

效率更高:

START TRANSACTION
UPDATE mytable SET foo = 'bar' WHERE (col1 = 813242) AND (col2 = 25343);
UPDATE mytable SET foo = 'bar' WHERE (col1 = 312643) AND (col2 = 8353);
UPDATE mytable SET foo = 'bar' WHERE (col1 = 843564) AND (col2 = 41233);
UPDATE mytable SET foo = 'bar' WHERE (col1 = 321312) AND (col2 = 5325);
UPDATE mytable SET foo = 'bar' WHERE (col1 = 554235) AND (col2 = 6321);
... x 10,000 times or more
COMMIT;

UPDATE mytable SET foo = 'bar' WHERE
((col1 = 16344) AND (col2 = 5456)) OR
((col1 = 42134) AND (col2 = 5436)) OR
((col1 = 84563) AND (col2 = 2321)) OR
((col1 = 43216) AND (col2 = 4267)) OR
((col1 = 53248) AND (col2 = 6234)) OR
... x 10,000 times or more

假设我有UNIQUE索引(col1,col2)

所以我的猜测是第一个选项很好,因为索引但它被拆分成多个查询,第二个选项很好,因为它只有一个查询但另一方面它执行全表扫描

这是EXPLAIN,不使用OR

  

输入:ref,possible_keys:myindex_UNIQUE,key:myindex_UNIQUE,ref:const

使用EXPLAIN时的OR

  

type:ALL,possible_keys:myindex_UNIQUE,key:null,ref:null

并且查询WHERE子句是否有任何限制?

我的目标是达到最高速度

3 个答案:

答案 0 :(得分:1)

我认为理论上第二个会更快,但它只是一个有根据的猜测。

它是一个语句,因此它可能需要更少的解析,更少的初始化,更少的往返。

第一个可能更快,因为它使用索引来查找记录。但是10.000索引查找也可能比全表扫描慢,所以我认为优势也不复存在。

多个语句可能较慢的一个原因是当您在程序循环中运行单独的更新时。在这种情况下,您获得了10.000倍的请求/响应开销。

只要您不这样做并且只是将更新作为单个请求发送,我认为性能将类似,任何差异将取决于服务器的硬件和配置,以及当前负载,表中的数据量以及更新的行数(或者它总是正好是10.000?)。总而言之,我无法给你一个确切的答案,但我希望我能让你深入了解影响这种表现的一些因素。

答案 1 :(得分:1)

根据评论中的对话,可能的解决方案:

如果您有一个大表和一个值列表来标识要更新的行,您可以为值列表创建一个帮助程序表。

根据问题中的示例,表格可能是这样的:

CREATE TABLE mytable_operation (
    col1 INT
  , col2 INT
) ENGINE = MEMORY;

请注意,create语句包含ENGINE = MEMORY提示,因此表将存储在内存而不是磁盘中。

在更新之前将值加载到此表中。

将所有值加载到帮助程序表后,可以使用以下查询来更新生产表中的值。

UPDATE
  mytable
SET
  foo = 'bar'
WHERE
  EXISTS (SELECT 1 FROM mytable_operation MO WHERE mytable.col1 = MO.col1 AND mytable.col2 = MO.col2)

当然,您可以使用任何DML语句来操作生产数据。 (使用联接更新,DELETEINSERT..ON DUPLICATE KEY等)

完成数据操作后,您可以截断或删除帮助程序表。

如果生产表中的行数略大,则此解决方案可能比问题中的解决方案更快。

答案 2 :(得分:-1)

在插入/更新时使用nosql引擎获得最快的结果

如果要查看索引的工作方式,请使用SELECT替换更新并使用explain运行它。这可以让您了解索引是否按照您希望的方式使用

EXPLAIN how to

并且不要忘记索引通常会减慢任何更新/插入速度 它仅在where子句中有用