Я использую базу данных MySQL на Raspberry Pi 3b + и использую некоторые хранимые процедуры.
Если я запускаю их, просто случайно они очень медленные.
Вот мой код:
DROP procedure IF EXISTS `Zeiterfassung`.`auswertung_jahr`;
DELIMITER $$
CREATE PROCEDURE `Zeiterfassung`.`auswertung_jahr` (IN `var_benutzer_id` INT(11), IN `var_jahr` INT(11))
BEGIN
#Variablen
DECLARE var_letzte_id, var_auswertung_jahr_id, var_sum_arbeitszeit_soll, var_sum_arbeitszeit_ist, var_sum_arbeitszeit_saldo, var_ferien_tage, var_diff_tage, var_arbeitspensum INT DEFAULT 0;
DECLARE var_sum_ferien_ist, var_sum_ferien_soll, var_sum_ferien_saldo, var_sum_krank_saldo, var_ferien_uebertrag, var_arbeitszeit_uebertrag FLOAT DEFAULT 0;
DECLARE var_eintritt, var_austritt, var_datum_von DATE;
#Abfrage, dieser Monat
SELECT auswertung_jahr_id INTO var_auswertung_jahr_id FROM auswertung_jahr WHERE jahr = var_jahr AND benutzer_id = var_benutzer_id;
IF var_auswertung_jahr_id = 0 THEN #wenn Jahr vorhanden
#wenn kein Jahr vorhanden Eintrag erstellen
INSERT INTO auswertung_jahr (benutzer_id, jahr) VALUES (var_benutzer_id, var_jahr);
SET var_letzte_id = LAST_INSERT_ID();
ELSE
SET var_letzte_id = var_auswertung_jahr_id;
END IF;
#Eintritt, Austritt wird gebraucht, um Anteil an Ferien in diesem Jahr zu berechnen.
SELECT
benutzer.eintritt, benutzer.austritt, benutzer.uebertrag_ueberzeit, benutzer.uebertrag_ferien, benutzer.arbeitspensum, benutzer.ferien_tage
INTO
var_eintritt, var_austritt, var_arbeitszeit_uebertrag, var_ferien_uebertrag, var_arbeitspensum, var_ferien_tage
FROM benutzer
WHERE benutzer.benutzer_id = var_benutzer_id;
#Summen für diesen Monat werden ausgerechnet
SELECT
IFNULL( SUM(arbeitszeit_soll), 0 ), IFNULL( SUM(arbeitszeit_ist), 0 ), IFNULL( SUM(ferien_saldo), 0 ), IFNULL( SUM(krank_saldo), 0 )
INTO
var_sum_arbeitszeit_soll, var_sum_arbeitszeit_ist, var_sum_ferien_ist, var_sum_krank_saldo
FROM
auswertung_monat
WHERE benutzer_id = var_benutzer_id AND jahr = var_jahr;
#Ferien SOLL ausrechnen
#Eintritt und Austritt im selben Jahr
IF var_jahr = YEAR(var_eintritt) AND var_jahr = YEAR(var_austritt) THEN
SELECT DATEDIFF(var_austritt, var_eintritt) INTO var_diff_tage;
SELECT var_ferien_tage / 365 * (var_diff_tage + 1) INTO var_sum_ferien_soll;
#Nur Eintritt in diesem Jahr
ELSEIF var_jahr = YEAR(var_eintritt) THEN
#Eintritt
SELECT CONCAT(var_jahr,'-12-31') INTO var_datum_von;
SELECT DATEDIFF(var_datum_von, var_eintritt) INTO var_diff_tage;
SELECT var_ferien_tage / 365 * (var_diff_tage + 1) INTO var_sum_ferien_soll;
#Nur Austritt in diesem Jahr
ELSEIF var_jahr = YEAR(var_austritt) THEN
SELECT CONCAT(var_jahr,'-01-01') INTO var_datum_von;
SELECT DATEDIFF(var_austritt, var_datum_von) INTO var_diff_tage;
SELECT var_ferien_tage / 365 * (var_diff_tage + 1) INTO var_sum_ferien_soll;
#Sonst wurde ganzes Jahr gearbeitet = volle Anzahl Ferien
ELSE
SELECT var_ferien_tage INTO var_sum_ferien_soll;
END IF;
#Bei Teilzeitarbeit wird das Ferien SOLL noch heruntergerechnet
SET var_sum_ferien_soll = var_sum_ferien_soll / 100 * var_arbeitspensum;
#Nach dem Prozentualen Ferien Ergebnis wird noch der Übertrag dazugerechnet, falls dieses Jahr das Eintrittsjah ist
IF var_jahr = YEAR(var_eintritt) THEN
#Übertrag von Ferien aus z.B. anderer Software werden dazugerechnet aber nur einmalig (Eintrittsjahr)
UPDATE
auswertung_jahr
SET
ferien_uebertrag = var_ferien_uebertrag,
arbeitszeit_uebertrag = var_arbeitszeit_uebertrag * 3600
WHERE
auswertung_jahr_id = var_letzte_id;
END IF;
#Ferien SALDO ausrechnen
SET var_sum_ferien_saldo = var_sum_ferien_soll - var_sum_ferien_ist;
#Arbeitszeit SALDO ausrechnen
SET var_sum_arbeitszeit_saldo = var_sum_arbeitszeit_soll - var_sum_arbeitszeit_ist;
#Summen eintragen
UPDATE
auswertung_jahr
SET
arbeitszeit_soll = var_sum_arbeitszeit_soll,
arbeitszeit_ist = var_sum_arbeitszeit_ist,
arbeitszeit_saldo = var_sum_arbeitszeit_saldo,
ferien_ist = var_sum_ferien_ist,
ferien_soll = var_sum_ferien_soll,
ferien_saldo = var_sum_ferien_saldo,
krank_saldo = var_sum_krank_saldo
WHERE
auswertung_jahr_id = var_letzte_id;
END$$
Я думаю, что он не может иметь ничего общего с кодом, потому что я могу выполнить процедуру, и в основном она очень быстрая.
Затем, если я повторю процедуру с точно такими же данными, она случайно замедлится.
Вот картинка, где я выполнял одну и ту же процедуру несколько раз подряд с точно такими же данными:
![enter image description here](https://i.stack.imgur.com/ewZ88.png)
Если я посмотрю на загрузку системы с помощью TOP, то больше ничего не получится, используя питание ..
Вот пример из медленного журнала:
CALL auswertung_jahr(5,2019);
# Time: 190430 20:13:43
# User@Host: root[root] @ localhost []
# Thread_id: 2 Schema: Zeiterfassung QC_hit: No
# Query_time: 3.389289 Lock_time: 0.000000 Rows_sent: 0 Rows_examined: 5
# Rows_affected: 0
SET timestamp=1556648023;
CALL auswertung_jahr(5,2019);
# Time: 190430 20:13:44
# User@Host: root[root] @ localhost []
# Thread_id: 2 Schema: Zeiterfassung QC_hit: No
# Query_time: 0.186437 Lock_time: 0.000000 Rows_sent: 0 Rows_examined: 5
# Rows_affected: 0
SET timestamp=1556648024;
Сначала более 3 секунд, затем 0,18 секунды
Я отключил кеш:
SET SESSION query_cache_type=0;