Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 程序缓慢更新记录_Mysql_Sql_Performance_Procedure - Fatal编程技术网

Mysql 程序缓慢更新记录

Mysql 程序缓慢更新记录,mysql,sql,performance,procedure,Mysql,Sql,Performance,Procedure,如何改进程序以更快地执行? 我有3个过程,第一个在第二个更新余额之前搜索余额,第三个我用来做处理,我调用前两个过程。 简而言之,当我插入一个表记录时,服务中的一个计时器通过调用过程PROC_PROCESSAR_SALDO来重做余额处理 DROP PROCEDURE IF EXISTS `PROC_SALDO_ANTERIOR`; DELIMITER $$ CREATE PROCEDURE `PROC_SALDO_ANTERIOR` ( IN codigo_Empresa_par IN

如何改进程序以更快地执行? 我有3个过程,第一个在第二个更新余额之前搜索余额,第三个我用来做处理,我调用前两个过程。 简而言之,当我插入一个表记录时,服务中的一个计时器通过调用过程PROC_PROCESSAR_SALDO来重做余额处理

DROP PROCEDURE IF EXISTS `PROC_SALDO_ANTERIOR`;

DELIMITER $$

CREATE PROCEDURE `PROC_SALDO_ANTERIOR` (
    IN codigo_Empresa_par INT,
    IN codigo_Filial_par INT,
    IN codigo_Conta_par INT,
    IN sequencia_par BIGINT(20),
    IN data_Hora_par DATETIME,
    OUT sequencia_ret BIGINT(20),
    OUT data_Hora_ret DATETIME,
    OUT saldo_Atual_ret DECIMAL(20, 2)
)
BEGIN

    SELECT SEQUENCIA, DATAHORA, SALDO_ATUAL INTO sequencia_ret, data_Hora_ret, saldo_Atual_ret
    FROM CONTAS_CORRENTES 
    WHERE CODIGO_EMPRESA = codigo_Empresa_par AND
    CODIGO_FILIAL = codigo_Filial_par AND
    CODIGO_CONTA = codigo_Conta_par AND 
    ((DATAHORA =data_Hora_par AND SEQUENCIA < sequencia_par) OR (DATAHORA < data_Hora_par)) 
    ORDER BY DATAHORA DESC, SEQUENCIA DESC LIMIT 1;

    if sequencia_ret IS NULL THEN
        SET sequencia_ret := 0;
        SET data_Hora_ret := '0001/01/01 12:00:00';
        SET saldo_Atual_ret := 0;
    END IF;
END;

DELIMITER ;



DROP PROCEDURE IF EXISTS `PROC_ATUALIZAR_SALDO`;

DELIMITER $$



CREATE PROCEDURE `PROC_ATUALIZAR_SALDO` (
    IN codigo_Empresa_par INT,
    IN codigo_Filial_par INT,
    IN codigo_Conta_par INT,
    IN sequencia_par BIGINT(20),
    IN data_Hora_par DATETIME,
    IN saldo_Atual_par DECIMAL(20,2)
)
BEGIN
    DECLARE SEQUENCIA_NEW BIGINT(20) DEFAULT 0;
    DECLARE DEBITO_NEW DECIMAL(20,2) DEFAULT 0;
    DECLARE CREDITO_NEW DECIMAL(20,2) DEFAULT 0;
    DECLARE SALDO_ANTERIOR DECIMAL(20,2) DEFAULT 0;
    DECLARE done INT DEFAULT FALSE;
    DECLARE cur  CURSOR FOR SELECT A.SEQUENCIA, A.DEBITO, A.CREDITO
                            FROM CONTAS_CORRENTES A
                            WHERE A.CODIGO_EMPRESA = codigo_Empresa_par AND
                            A.CODIGO_FILIAL = codigo_Filial_par AND
                            A.CODIGO_CONTA = codigo_Conta_par AND 
                            ((A.DATAHORA = data_Hora_par AND 
                            A.SEQUENCIA > sequencia_par) OR
                            (A.DATAHORA > data_Hora_par))
                            ORDER BY A.DATAHORA ASC,
                            A.SEQUENCIA ASC;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

    START TRANSACTION;

    SET SALDO_ANTERIOR := saldo_Atual_par;   


    OPEN cur;
        ins_loop: LOOP
            FETCH cur INTO SEQUENCIA_NEW, DEBITO_NEW, CREDITO_NEW;
            IF done THEN
                LEAVE ins_loop;
            END IF;

            SET SALDO_ANTERIOR := SALDO_ANTERIOR - DEBITO_NEW + CREDITO_NEW;

            UPDATE CONTAS_CORRENTES SET SALDO_ATUAL = SALDO_ANTERIOR
            WHERE CODIGO_EMPRESA = codigo_Empresa_par AND
            CODIGO_FILIAL = codigo_Filial_par AND 
            CODIGO_CONTA = codigo_Conta_par AND 
            SEQUENCIA = SEQUENCIA_NEW;
        END LOOP;
    CLOSE cur;  

    COMMIT;

END $$

DELIMITER ;

DROP PROCEDURE IF EXISTS `PROC_PROCESSAR_SALDO`;

DELIMITER $$

CREATE PROCEDURE `PROC_PROCESSAR_SALDO` (
    IN codigo_Empresa_new INT,
    IN codigo_Filial_new INT,
    IN codigo_Conta_new INT,
    IN sequencia_new BIGINT(20),
    IN data_Hora_new DATETIME
)
BEGIN

    CALL PROC_SALDO_ANTERIOR(codigo_Empresa_new, codigo_Filial_new, codigo_Conta_new, sequencia_new, 
                             data_Hora_new, @sequencia_ret, @data_Hora_ret, @saldo_Atual_ret);

    CALL PROC_ATUALIZAR_SALDO(codigo_Empresa_new, codigo_Filial_new, codigo_Conta_new, @sequencia_ret, 
                              @data_Hora_ret, @saldo_Atual_ret);
END $$

DELIMITER ;

CALL PROC_PROCESSAR_SALDO(@CODIGO_EMPRESA, @CODIGO_FILIAL, @CODIGO_CONTA, @SEQUENCIA, @DATAHORA);
DROP程序(如果存在)`PROC_SALDO_front`;
分隔符$$
创建程序'PROC_SALDO_front'(
在codigo_Empresa_par INT,
在codigo_durth_INT中,
在codigo\u Conta\u par INT中,
依次为(20),
在data_Hora_par DATETIME中,
按顺序排列(20),
输出日期时间的数据,
输出十进制数(20,2)
)
开始
选择SEQUENCIA、DATAHORA、SALDO_-ATUAL进入SEQUENCIA_-ret、data_-Hora_-ret、SALDO_-ATUAL_-ret
来自康塔斯·科伦特斯
式中,CODIGO_EMPRESA=CODIGO_EMPRESA_par和
CODIGO_孝顺=CODIGO_孝顺
CODIGO\u CONTA=CODIGO\u CONTA\u par和
((数据时间=数据时间和顺序<顺序时间)或(数据时间<数据时间)
DATAHORA DESC的订单,SEQUENCIA DESC限额1;
如果sequencia_ret为空,则
设置顺序:=0;
设置数据时间:0001/01/01 12:00:00;
设置saldo_Atual_ret:=0;
如果结束;
结束;
定界符;
删除程序(如果存在)`PROC_ATUALIZAR_SALDO`;
分隔符$$
创建过程“PROC_ATUALIZAR_SALDO”(
在codigo_Empresa_par INT,
在codigo_durth_INT中,
在codigo\u Conta\u par INT中,
依次为(20),
在data_Hora_par DATETIME中,
十进制(20,2)
)
开始
声明SEQUENCIA_NEW BIGINT(20)默认值为0;
声明DEBITO_新十进制(20,2)默认为0;
声明CREDITO_新十进制(20,2)默认为0;
声明SALDO_前十进制(20,2)默认为0;
声明done INT DEFAULT FALSE;
为选择A.SEQUENCIA、A.DEBITO、A.CREDITO声明当前光标
来自CONTAS_CORRENTES A
其中A.CODIGO_EMPRESA=CODIGO_EMPRESA_par和
A.CODIGO_孝顺=CODIGO_孝顺
A.CODIGO_CONTA=CODIGO_CONTA_par和
((A.DATAHORA=数据时间段和
A.顺序>顺序)或
(A.DATAHORA>data_Hora_par))
由A.DATAHORA ASC订购,
A.SEQUENCIA ASC;
声明未找到的继续处理程序SET done=TRUE;
启动交易;
将SALDO_前方设置为:=SALDO_Atual_par;
开放cur;
ins_循环:循环
将cur存入顺序新、借记新、贷记新;
如果这样做的话
离开ins_循环;
如果结束;
设置SALDO_-previous:=SALDO_-previous-DEBITO_-NEW+CREDITO_-NEW;
更新CONTAS_CORRENTES SET SALDO_ATUAL=SALDO_
式中,CODIGO_EMPRESA=CODIGO_EMPRESA_par和
CODIGO_孝顺=CODIGO_孝顺
CODIGO\u CONTA=CODIGO\u CONTA\u par和
SEQUENCIA=SEQUENCIA_NEW;
端环;
封闭电流;
犯罪
结束$$
定界符;
删除过程(如果存在)`PROC_PROCESSAR_SALDO`;
分隔符$$
创建过程“PROC\u PROCESSAR\u SALDO”(
在codigo_Empresa_new INT,
在codigo_新INT中,
在codigo_Conta_new INT中,
依次为新比基特(20),
在数据时间中,新的日期时间
)
开始
呼叫PROC_SALDO_Previous(codigo_Empresa_new、codigo_Durth_new、codigo_Conta_new、sequencia_new、,
数据(新),"顺序","数据"(新),"数据","萨尔多"(新),;
请致电PROC_Atalizar_SALDO(codigo_Empresa_new,codigo_Durth_new,codigo_Conta_new,@sequencia_ret,
@数据(Hora_ret,@saldo_Atual_ret);
结束$$
定界符;
调用PROC_PROCESSAR_SALDO(@CODIGO_EMPRESA、@CODIGO_durth、@CODIGO_CONTA、@SEQUENCIA、@DATAHORA);

您必须检查是什么导致查询速度变慢。基本上有两件事需要检查:

  • 单个查询是否使用索引
  • 游标循环是否会产生太多的行(可能是一个稍微未优化的)循环中的查询,从而导致性能降低

使用
EXPLAIN
检查单个查询以供索引使用。您还可以在每个查询中添加
select now()
,然后执行该过程,您应该可以看到哪个部分占用了时间。

似乎所有3个过程都可以分解为一个
INSERT。。重复密钥更新时..
语句!