我在构建数据库时遇到了一个问题,需要通过错误消息字段连接两个表,该字段当前设置为 varchar(255)。这(显然)会在执行连接时导致性能和锁定问题。我的初始声明卡在任何大于 1000 行的更新上。这是代码:
UPDATE Integration_Detail D
JOIN Integration_Error_Descriptor E
ON D.Error_Message = E.Error_Message
SET D.Error_Key = E.Error_Key
WHERE D.Error_Key is null;
我决定改为使用存储过程,以便将 UPDATE 语句分解成更小的部分。这可行,但在性能方面并不理想,因为我使用的是 while 循环并以 200 为一组进行更新。过程代码如下所示:
CREATE PROCEDURE update_detail_table()
BEGIN
declare rowsToProcess int default 0;
set rowsToProcess =
(select count(*)
from Integration_Report.Integration_Detail
where Error_Key is null);
CREATE TABLE Integration_Report.temp_error_processing (
Detail_Key bigint DEFAULT null,
Error_Key bigint DEFAULT null
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
while rowsToProcess > 0 DO
INSERT INTO Integration_Report.temp_error_processing
(SELECT D.Detail_Key, E.Error_Key
FROM Integration_Report.Integration_Detail D
JOIN Integration_Report.Integration_Error_Descriptor E
ON D.Error_Message = E.Error_Message
WHERE D.Error_Key is null
ORDER BY D.Insert_Datetime desc
LIMIT 200);
UPDATE Integration_Report.Integration_Detail D
JOIN Integration_Report.temp_error_processing T
ON D.Detail_Key = T.Detail_Key
SET D.Error_Key = T.Error_Key;
TRUNCATE TABLE Integration_Report.temp_error_processing;
set rowsToProcess =
(select count(*)
from Integration_Report.Integration_Detail
where Error_Key is null);
end while;
drop table Integration_Report.temp_error_processing;
END;
有没有一种方法可以更快且使用更少的内存来完成此操作?我之前没有写过很多程序,所以如果我的代码也很丑陋,请告诉我。
感谢您的帮助。
最佳答案
您所拥有的分块效率低下的部分原因是它会反复跨过已完成的行。目标是每次查看不同的 200 行。
我在这里讨论细节:http://mysql.rjweb.org/doc.php/deletebig#deleting_in_chunks
请注意,它使用 PRIMARY KEY
遍历表格以避免重新扫描。而且它不一定每次都处理完整的 block 大小。并且不需要 COUNT(*)
,因为到达表的末尾就足以终止。
关于mysql - 加入长文本字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45442858/