Mysql 单个事务中的多个更新与使用大WHERE子句的一个更新

Mysql 单个事务中的多个更新与使用大WHERE子句的一个更新,mysql,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

效率更高的是:

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;

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

所以我猜第一个选项很好,因为它是索引,但它被分割成多个查询,第二个选项很好,因为它只是一个查询,但另一方面,它做完整的表扫描

这是不使用
时的
解释:

类型:ref,可能的\u键:myindex\u UNIQUE,键:myindex\u UNIQUE,ref:const

这是使用
时的
解释:

类型:ALL,可能的\u键:myindex\u UNIQUE,键:null,ref:null

查询
WHERE
子句是否有限制


我的目标是最大速度

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

如果要查看索引的工作方式,请使用SELECT替换更新,并使用explain运行更新。这会让你知道索引是否按你想要的方式使用

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

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

这是一条语句,因此可能需要更少的解析、更少的初始化和更少的往返

第一个可能更快,因为它使用索引来查找记录。但是10.000索引查找可能也比完整表扫描慢,所以我认为这一优势也消失了

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


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

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

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

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

CREATE TABLE mytable_operation (
    col1 INT
  , col2 INT
) ENGINE = MEMORY;
请注意,create语句包含
ENGINE=MEMORY
提示,因此表将存储在内存中而不是磁盘中

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

将所有值加载到helper表后,可以使用以下查询更新生产表中的值

UPDATE
  mytable
SET
  foo = 'bar'
WHERE
  EXISTS (SELECT 1 FROM mytable_operation MO WHERE mytable.col1 = MO.col1 AND mytable.col2 = MO.col2)
当然,您可以使用任何DML语句来操作生产数据。(使用连接更新,
删除
在重复键上插入..等)

完成数据操作后,可以截断或删除辅助表


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

因此模式为
col1=N和col2=N+1
(也就是说,
col2=col1+1
?这可能是可能的,而且可能在连接时效率更高…@MichaelBerkowski没有模式,这只是一个示例Peter,你是否从一开始就重复更新语句或块10000次?@Peter:我知道这不是直接的答案,但我建议你不要使用trans操作解决方案,如果可以接受,并且每个查询要更新的记录数很少,则使用单独的UPDATE语句。长事务不是好事。嗯……一个可能的解决方案是将API调用的结果插入到临时/辅助表中(可能带有索引)并将该表用作更新查询的筛选器。如果您的表包含的行数远远超过要更新的行数,这可能会有所帮助。您可以在更新后截断或删除临时/helper表。临时表可以使用基于内存的存储引擎来最大化性能。索引会降低插入速度,但会降低更新速度语句通常也有where子句。如果索引位于更新字段而不是搜索字段上,则索引会减慢更新速度。基本上,如果索引导致索引更改,则索引会减慢DML语句的速度。切换到noSQL不是一个选项。我进行了解释查询,我怀疑只有第一个选项正确使用了索引
UPDATE
  mytable
SET
  foo = 'bar'
WHERE
  EXISTS (SELECT 1 FROM mytable_operation MO WHERE mytable.col1 = MO.col1 AND mytable.col2 = MO.col2)