Процедура медленного обновления записей - PullRequest
0 голосов
/ 30 октября 2019

Как улучшить процедуру, чтобы выполнить быстрее? У меня есть 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);

1 Ответ

0 голосов
/ 31 октября 2019

Вы должны проверить, что делает запросы медленными. В основном вам нужно проверить две вещи:

  • Используют ли отдельные запросы индексы?
  • Производит ли цикл курсора столько строк, что (слегка неоптимизированный) запрос в цикле добавляетприводящий к низкой производительности

Проверьте отдельные запросы с помощью EXPLAIN для использования индекса. Вы также можете добавить select now() after в каждый запрос и выполнить процедуру, и вы должны увидеть, какая часть потребляет время.

...