我正在使用oracle FORALL构造来提高PL / SQL块的性能。我正在写下FORALL的'之前'和'之后'代码 -
BEFORE:
FOR employee_rec IN (SELECT employee_id
FROM employees
WHERE department_id =
increase_salary_prc.p_department_id_in)
LOOP
check_eligibility_prc (employee_rec.employee_id, l_eligible);
IF l_eligible THEN
UPDATE employees emp
SET emp.salary = emp.salary + emp.salary * increase_salary_prc.p_increase_pct_in
WHERE emp.employee_id = employee_rec.employee_id;
END IF;
END LOOP;
AFTER:
TYPE employee_ids_t IS TABLE OF employees.employee_id%TYPE INDEX BY PLS_INTEGER;
l_employee_ids employee_ids_t;
l_eligible_ids employee_ids_t;
BEGIN
SELECT employee_id
BULK COLLECT INTO l_employee_ids
FROM employees
WHERE department_id = increase_salary_prc.p_department_id_in;
FOR indx IN 1..l_employee_ids.COUNT
LOOP
check_eligibility_prc (l_employee_ids(indx),
l_eligible);
IF l_eligible THEN
l_eligible_ids(l_eligible_ids.COUNT + 1) := l_employee_ids(indx);
END IF;
END LOOP;
FORALL indx IN 1..l_eligible_ids.COUNT
UPDATE employees emp
SET emp.salary = emp.salary + emp.salary * increase_salary_prc.p_increase_pct_in
WHERE emp.employee_id = l_eligible_ids(indx);
其他信息 -
员工总数记录--20000 有2个部门--15和16,每个部门包含10000个记录。程序仅针对部门15运行。在10000中,符合更新条件的是5000。
check_eligibility_prc的代码 -
SELECT eligible
INTO l_eligible
FROM EMPLOYEES
WHERE employee_id = p_emp_id;
IF l_eligible = 'Y' THEN
p_eligible := TRUE;
ELSE
p_eligible := FALSE;
END IF;
在'之前'代码中 - 1. for循环运行10000次 2.内部循环中的'IF'是真实的5000次。因此更新查询运行5000次。
在'之后'代码中 - 1.循环运行10000次。 2.内部循环中的'IF'是真实的5000次。 3. l_eligible_ids insidd FORALL循环包含5000条要更新的记录
使用'before'块,代码运行637.42
秒。但令人惊讶的是,“后”代码花费了极少的额外时间。这需要637.545
秒。
任何人都可以就此为何发生任何指示吗? BULK COLLECT和FORALL假设减少了所花费的时间。相反,它增加了执行块的时间。
答案 0 :(得分:1)
尝试
update employees emp
set emp.salary = emp.salary + emp.salary * increase_salary_prc.p_increase_pct_in
where emp.department_id = increase_salary_prc.p_department_id_in
and emp.eligible = 'Y';
它看起来完全一样但速度会快得多。
P.S。十分钟是这些价值的令人难以置信的低速。即使有10 000个不必要的选择。