我正在开发一个 MySQL 过程,该过程对包含超过 25,000 条记录的 Products 表执行更新。该过程运行(通常锁定)非常慢,我需要帮助优化它以获得更好的性能。
问题: 该过程根据与 TemporaryProducts 表的比较来更新 Products 表中的 IsActive 和 IsDeleted 字段。具体来说,它执行以下操作:
在 Products 表中查找其 Name 字段在 TemporaryProducts 表的 StoreType 字段中不存在的产品。 为产品表中的这些产品设置 IsActive = 0 和 IsDeleted = 1。
这是当前程序:
BEGIN
UPDATE Products
SET IsActive = 0, IsDeleted = 1
WHERE Name NOT IN (SELECT StoreType FROM TemporaryProducts)
AND IsActive = 1 AND IsDeleted = 0;
END;
表结构 产品表:
临时产品表:
我尝试过的:
索引:
为两个表中的相关字段添加索引:
产品:(名称、IsActive、IsDeleted)
临时产品:(商店类型)
用 LEFT JOIN 替换 NOT IN: 我尝试使用
LEFT JOIN
重写查询,如下所示:
UPDATE Products p
LEFT JOIN TemporaryProducts t ON p.Name = t.StoreType
SET p.IsActive = 0, p.IsDeleted = 1
WHERE t.StoreType IS NULL
AND p.IsActive = 1 AND p.IsDeleted = 0;
我的问题:
我还可以使用哪些其他策略来优化此更新查询以获得更好的性能?
即使添加了索引,哪些潜在瓶颈会导致查询运行缓慢?
任何指导或建议将不胜感激。 预先感谢您!
有两件事你可以尝试让这项工作变得更好。
在
Products (IsActive, IsDeleted, Name)
上添加索引。这些列与您已有的复合索引相同,但最后是 Name
。这可能比您拥有的索引更好地支持您的 WHERE 子句。
在 UPDATE 查询中放入 LIMIT 100 或类似的值。然后循环重复,直到 ROW_COUNT() 为零。这将减少单个查询的大小,并使每个查询占用的时间更少。
显然,如果您需要以“原子”方式进行所有更改,以便表的其他用户不会注意到部分完成的更新,则您不能这样做。