Fab*_*bio 3 mysql performance procedure cursor
我使用游标创建了一个Mysql程序,但运行速度太慢......它的输出速度在40到60行之间..请参阅:
DELIMITER $$
CREATE PROCEDURE sp_create(IN v_idsorteio INT,OUT afetados INT)
BEGIN
DECLARE done INT default 0;
DECLARE vc_idsocio INT;
DECLARE z INT;
DECLARE cur1 CURSOR FOR select IdSocio from socios where Sorteio=1 and Finalizado='S' and CodClientes IS NOT NULL;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;
SET z=1;
OPEN cur1;
FETCH cur1 INTO vc_idsocio;
WHILE done=0 DO
-- SELECT register as t;
insert INTO socios_numeros_sorteio (IdSocio,IdSorteio,NumerodeSorteio) VALUES (vc_idsocio,v_idsorteio,z);
FETCH cur1 INTO vc_idsocio;
SET z = z+1;
END WHILE;
CLOSE cur1;
Select z-1 as total INTO afetados;
END$$
DELIMITER ;
Run Code Online (Sandbox Code Playgroud)
我该如何改进呢?
spe*_*593 11
这很慢,因为您逐行循环遍历结果集,并为返回的每一行执行单独的insert语句.这就是为什么它会变慢的原因.
让我们简要总结一下你在做什么.首先,您正在运行查询:
select IdSocio
from socios
where Sorteio=1
and Finalizado='S'
and CodClientes IS NOT NULL;
Run Code Online (Sandbox Code Playgroud)
(显然这些行的返回顺序并不重要.)
然后,对于从该查询返回的每一行,您希望将行插入另一个表中.
insert INTO socios_numeros_sorteio
(IdSocio
,IdSorteio
,NumerodeSorteio
) VALUES
(vc_idsocio
,v_idsorteio
,z);
Run Code Online (Sandbox Code Playgroud)
第一列的值来自查询返回的值.将为第二列的值分配一个作为参数传递给过程的值.并且第三列的值来自从1开始的计数器,并且每行增加1.
MySQL经过优化,可以执行这样的操作.但它没有进行优化,使用循环遍历游标的存储过程来执行此操作.
如果您希望获得一些合理的性能,则需要显着减少运行的单个INSERT语句的数量,而是考虑在"集合"而不是单个行中处理数据.一种方法是将行批处理为"扩展插入"语句,它可以一次插入多行.(您可以在一个语句中插入的行数实际上受max_allowed_packet限制.)
该方法将显着提高性能,但它不会避免游标的开销,将每一行提取到过程变量中.
这样的事情(在程序的主体中)可能会执行更多,更好,因为它从您的选择中获取结果集并一举将所有行插入到目标表中,而不必费心去更新过程中变量的值.
BEGIN
SET @idsorteio = v_idsorteio;
INSERT INTO socios_numeros_sorteio
( IdSocio
, IdSorteio
, NumerodeSorteio
)
SELECT s.IdSocio AS IdSocio
, @idsorteio AS IdSorteio
, @z := @z+1 AS NumerodeSorteio
FROM socios s
JOIN (SELECT @z := 0) z
WHERE s.Sorteio=1
AND s.Finalizado='S'
AND s.CodClientes IS NOT NULL;
SELECT ROW_NUMBER() INTO afetados;
END$$
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5707 次 |
| 最近记录: |