Я создал хранимую процедуру с параметром OUT
для обработки INSERT
операций автоматизации на основе значений других таблиц. Я также сделал сохраненную функцию для той же операции. Я сталкиваюсь с проблемой времени выполнения, поскольку оба они сильно отличаются друг от друга, что вызывает у меня беспокойство, и я не знаю, почему это так.
Ниже приведены итоговые значения таблицы:
- 2016 строк в
emp_personal
Я использую MariaDB 10.3.14
. Я тестирую с HeidiSQL 10.1.0.5577
.
Я также попытался вызвать его из Node.JS
, используя MariaDB Node.js Connector . Но в обоих случаях у меня был почти одинаковый результат.
Это хранимая процедура
CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_auto_attendance`(
OUT `result` INT
)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE empId,done,isHoliday,isEmpHoliday,isWeekOff,isApprovedLeave,insertedRows INT DEFAULT 0;
DECLARE attendance VARCHAR(20) DEFAULT 'Present';
DECLARE empIds VARCHAR(500) DEFAULT '';
-- declare cursor with all employee Ids who are active
DECLARE empIds_cursor CURSOR FOR
SELECT id from emp_personal where isActive=1;
-- declare NOT FOUND handler
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
-- Check if today is holiday
SELECT COUNT(id) INTO isHoliday
FROM apexa_portal.public_holiday_dates
WHERE dateOfHoliday= CURDATE();
OPEN empIds_cursor;
get_id: LOOP
SET attendance = 'Present';
FETCH empIds_cursor INTO empId;
-- Following check if NOT FOUND handler has called, if yes exit loop else continue. NOTE: If you don't write this, it will be infinite loop.
IF done = 1 THEN
LEAVE get_id;
END IF;
-- Check if public holiday for employee
IF isHoliday > 0 THEN
SELECT COUNT(phtd.isActive) INTO isEmpHoliday FROM public_holiday_template_days as phtd
LEFT JOIN emp_office_details as eod ON eod.publicHolidayTemplate=phtd.templateId
LEFT JOIN public_holiday_dates as phd ON phd.pub_holiday_id=phtd.holidayId
WHERE eod.empID=empId AND phd.dateOfHoliday=CURDATE() AND phtd.isActive=1;
IF isEmpHoliday > 0 THEN
SET attendance = 'Public Holiday';
END IF;
END IF;
-- if not public holiday, Check if week off
IF attendance <> 'Public Holiday' THEN
SELECT COUNT(eowd.id) INTO isWeekOff FROM emp_office_working_days as eowd
WHERE DAY=DAYOFWEEK(CURDATE()) AND eowd.empId=empId AND eowd.isActive=0;
IF isWeekOff > 0 THEN
SET attendance = 'Week Off';
END IF;
END IF;
-- if not week off, Check if approved leave
IF attendance <> 'Week Off' THEN
SELECT COUNT(la.id) INTO isApprovedLeave FROM leave_application as la
WHERE la.fromDate <= CURDATE() AND la.toDate >= CURDATE() AND la.empID=empId AND la.leaveStatus='Approved';
IF isApprovedLeave > 0 THEN
SET attendance = 'Approved Leave';
END IF;
END IF;
-- insert attendance
INSERT INTO attendance_master(empID,dateOfAttendance,attendance) VALUES(empId,CURDATE(),attendance);
SET insertedRows = insertedRows + 1;
END LOOP get_id;
CLOSE empIds_cursor;
SET result = insertedRows;
END
Это хранимая функция
CREATE DEFINER=`root`@`localhost` FUNCTION `test_auto_att_func`()
RETURNS int(11)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE empId,done,isHoliday,isEmpHoliday,isWeekOff,isApprovedLeave,insertedRows INT DEFAULT 0;
DECLARE attendance VARCHAR(20) DEFAULT 'Present';
DECLARE empIds VARCHAR(500) DEFAULT '';
-- declare cursor with all employee Ids who are active
DECLARE empIds_cursor CURSOR FOR
SELECT id from emp_personal where isActive=1;
-- declare NOT FOUND handler
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
-- Check if today is holiday
SELECT COUNT(id) INTO isHoliday
FROM apexa_portal.public_holiday_dates
WHERE dateOfHoliday= CURDATE();
OPEN empIds_cursor;
get_id: LOOP
SET attendance = 'Present';
FETCH empIds_cursor INTO empId;
-- Following check if NOT FOUND handler has called, if yes exit loop else continue. NOTE: If you don't write this, it will be infinite loop.
IF done = 1 THEN
LEAVE get_id;
END IF;
-- Check if public holiday for employee
IF isHoliday > 0 THEN
SELECT COUNT(phtd.isActive) INTO isEmpHoliday FROM public_holiday_template_days as phtd
LEFT JOIN emp_office_details as eod ON eod.publicHolidayTemplate=phtd.templateId
LEFT JOIN public_holiday_dates as phd ON phd.pub_holiday_id=phtd.holidayId
WHERE eod.empID=empId AND phd.dateOfHoliday=CURDATE() AND phtd.isActive=1;
IF isEmpHoliday > 0 THEN
SET attendance = 'Public Holiday';
END IF;
END IF;
-- if not public holiday, Check if week off
IF attendance <> 'Public Holiday' THEN
SELECT COUNT(eowd.id) INTO isWeekOff FROM emp_office_working_days as eowd
WHERE DAY=DAYOFWEEK(CURDATE()) AND eowd.empId=empId AND eowd.isActive=0;
IF isWeekOff > 0 THEN
SET attendance = 'Week Off';
END IF;
END IF;
-- if not week off, Check if approved leave
IF attendance <> 'Week Off' THEN
SELECT COUNT(la.id) INTO isApprovedLeave FROM leave_application as la
WHERE la.fromDate <= CURDATE() AND la.toDate >= CURDATE() AND la.empID=empId AND la.leaveStatus='Approved';
IF isApprovedLeave > 0 THEN
SET attendance = 'Approved Leave';
END IF;
END IF;
-- insert attendance
INSERT INTO attendance_master(empID,dateOfAttendance,attendance) VALUES(empId,CURDATE(),attendance);
SET insertedRows = insertedRows + 1;
END LOOP get_id;
CLOSE empIds_cursor;
RETURN insertedRows;
END
Время выполнения сохраненной функции
SELECT `test_auto_att_func`();
/* Affected rows: 0 Found rows: 1 Warnings: 0 Duration for 1 query: 0.328 sec. */
Время выполнения хранимой процедуры
CALL `sp_auto_attendance`(@res);
SELECT @res;
/* Affected rows: 6,049 Found rows: 1 Warnings: 0 Duration for 2 queries: 00:01:21.6 */
Выход сохраненной функции и Выход хранимой процедуры
Может кто-нибудь объяснить, почему это происходит? И если я делаю что-то не так, пожалуйста, дайте мне знать, как мне это исправить?
Спасибо.