我编写了一个在Oracle 9i中运行的PL / SQL块,它通过数据库链路处理来自11g Oracle DB的数据。但是代码正在完成。处理的数据大约是1000到2000条记录。我在这里发布代码:
DECLARE
v_last_comment VARCHAR2 (255);
v_check NUMBER := 0;
CURSOR noschedule_progs
IS
SELECT /*+ DRIVING_SITE(fcr) */
fcr.request_id,
DECODE
(fcpt.user_concurrent_program_name,
'Report Set', fcr.description,
'Request Set Stage', fcr.description,
fcpt.user_concurrent_program_name
) user_concurrent_program_name,
fcr.description, fcr.argument_text, fcr.concurrent_program_id,
fcr.parent_request_id, fcr.actual_start_date,
fcr.actual_completion_date,
ROUND ( (fcr.actual_completion_date - fcr.actual_start_date)
* 24
* 60,
4
) runtime,
'No Schedule' program_status, fu.user_name,
frt.responsibility_name, fcr.logfile_name
FROM apps.fnd_concurrent_requests@db_link fcr,
apps.fnd_concurrent_programs_tl@db_link fcpt,
apps.fnd_user@db_link fu,
apps.fnd_responsibility_tl@db_link frt
WHERE fcr.concurrent_program_id = fcpt.concurrent_program_id
AND fcr.requested_by = fu.user_id
AND fcr.responsibility_id = frt.responsibility_id
AND fcr.responsibility_application_id = frt.application_id
AND fcr.phase_code = 'C'
AND fcr.status_code IN ('C', 'G', 'E', 'X')
AND fcr.actual_completion_date >= SYSDATE - 1 / 24
AND fcr.request_id NOT IN (
SELECT NVL (parent_request_id, 1)
FROM apps.fnd_concurrent_requests@db_link)
AND fcr.requested_by = 1508715
AND fcr.request_id NOT IN (SELECT request_id
FROM allen.alert_main
WHERE program_status = 'No Schedule');
PROCEDURE check_schedule (p_request_id IN NUMBER)
IS
v_count NUMBER (2);
v_parent_id NUMBER (15);
v_last_updated_by NUMBER (15);
v_program VARCHAR2 (255);
v_parent_program VARCHAR2 (255);
v_description VARCHAR2 (255);
v_status VARCHAR2 (2);
BEGIN
SELECT NVL (MAX (phase_code), 'X')
INTO v_status
FROM apps.fnd_concurrent_requests@db_link
WHERE request_id = p_request_id;
IF v_status != 'R'
THEN
SELECT NVL (MAX (description), 'None')
INTO v_description
FROM apps.fnd_concurrent_requests@db_link
WHERE request_id = p_request_id;
SELECT COUNT (*)
INTO v_count
FROM apps.fnd_concurrent_requests@db_link
WHERE parent_request_id = p_request_id
AND concurrent_program_id =
(SELECT concurrent_program_id
FROM apps.fnd_concurrent_requests@db_link
WHERE request_id = p_request_id)
AND NVL (description, 'None') = v_description;
IF v_count = 0
THEN
SELECT NVL (MAX (parent_request_id), 1)
INTO v_parent_id
FROM apps.fnd_concurrent_requests@db_link
WHERE request_id = p_request_id;
SELECT NVL (MAX (last_updated_by), 0)
INTO v_last_updated_by
FROM apps.fnd_concurrent_requests@db_link
WHERE request_id = p_request_id;
IF v_parent_id = -1
THEN
IF v_last_updated_by != 4
THEN
INSERT INTO ikndba.rac_aso_alert_main
SELECT /*+ DRIVING_SITE(fcr) */
ikndba.rac_aso_alert_seq.NEXTVAL, fcr.request_id,
DECODE
(fcpt.user_concurrent_program_name,
'Report Set', fcr.description,
'Request Set Stage', fcr.description,
fcpt.user_concurrent_program_name
) user_concurrent_program_name,
fcr.argument_text, fcr.concurrent_program_id,
fcr.parent_request_id, fcr.actual_start_date,
fcr.actual_completion_date,
ROUND ( ( fcr.actual_completion_date
- fcr.actual_start_date
)
* 24
* 60,
4
) runtime,
'No Schedule' program_status, fu.user_name,
frt.responsibility_name, fcr.logfile_name,
SYSDATE, 'Program Not in Schedule', NULL, 'OPEN',
'SYSTEM'
FROM apps.fnd_concurrent_requests@db_link fcr,
apps.fnd_concurrent_programs_tl@db_link fcpt,
apps.fnd_user@db_link fu,
apps.fnd_responsibility_tl@db_link frt
WHERE fcr.concurrent_program_id =
fcpt.concurrent_program_id
AND fcr.requested_by = fu.user_id
AND fcr.responsibility_id = frt.responsibility_id
AND fcr.responsibility_application_id =
frt.application_id
AND fcr.request_id = p_request_id
AND fcr.request_id NOT IN (
SELECT request_id
FROM allen.alert_main
WHERE program_status = 'No Schedule');
commit
END IF;
ELSE
SELECT NVL (MAX (DECODE (fcpt.user_concurrent_program_name,
'Report Set', fcr.description,
'Request Set Stage', fcr.description,
fcpt.user_concurrent_program_name
)
),
'Purged'
)
INTO v_program
FROM apps.fnd_concurrent_requests@db_link fcr,
apps.fnd_concurrent_programs_tl@db_link fcpt
WHERE request_id = p_request_id
AND fcr.concurrent_program_id = fcpt.concurrent_program_id;
SELECT NVL (MAX (DECODE (fcpt.user_concurrent_program_name,
'Report Set', fcr.description,
'Request Set Stage', fcr.description,
fcpt.user_concurrent_program_name
)
),
'Purged'
)
INTO v_parent_program
FROM apps.fnd_concurrent_requests@db_link fcr,
apps.fnd_concurrent_programs_tl@db_link fcpt
WHERE request_id = v_parent_id
AND fcr.concurrent_program_id = fcpt.concurrent_program_id;
IF v_parent_program = v_program AND v_program != 'Purged'
THEN
INSERT INTO ikndba.rac_aso_alert_main
SELECT /*+ DRIVING_SITE(fcr) */
ikndba.rac_aso_alert_seq.NEXTVAL, fcr.request_id,
DECODE
(fcpt.user_concurrent_program_name,
'Report Set', fcr.description,
'Request Set Stage', fcr.description,
fcpt.user_concurrent_program_name
) user_concurrent_program_name,
fcr.argument_text, fcr.concurrent_program_id,
fcr.parent_request_id, fcr.actual_start_date,
fcr.actual_completion_date,
ROUND ( ( fcr.actual_completion_date
- fcr.actual_start_date
)
* 24
* 60,
4
) runtime,
'No Schedule' program_status, fu.user_name,
frt.responsibility_name, fcr.logfile_name,
SYSDATE, 'Program Not in Schedule', NULL, 'OPEN',
'SYSTEM'
FROM apps.fnd_concurrent_requests@db_link fcr,
apps.fnd_concurrent_programs_tl@db_link fcpt,
apps.fnd_user@db_link fu,
apps.fnd_responsibility_tl@db_link frt
WHERE fcr.concurrent_program_id =
fcpt.concurrent_program_id
AND fcr.requested_by = fu.user_id
AND fcr.responsibility_id = frt.responsibility_id
AND fcr.responsibility_application_id =
frt.application_id
AND fcr.request_id = p_request_id
AND fcr.request_id NOT IN (
SELECT request_id
FROM allen.alert_main
WHERE program_status =
'No Schedule');
COMMIT;
ELSE
SELECT NVL (MAX (parent_request_id), 1)
INTO v_parent_id
FROM apps.fnd_concurrent_requests@db_link
WHERE request_id =v_parent_id;
check_schedule (v_parent_id);
END IF;
END IF;
END IF;
END IF;
END;
BEGIN
FOR noschedule_progs_row IN noschedule_progs
LOOP
check_schedule (noschedule_progs_row.request_id);
END LOOP;
COMMIT;
EXCEPTION
WHEN OTHERS
THEN
ROLLBACK;
DBMS_OUTPUT.put_line (SQLCODE);
END;
/
有没有办法提高这项计划的效率?
答案 0 :(得分:1)
您发布了一长串代码并没有实际细节(性能配置文件,数据量,业务逻辑等)。所以你能想到的最好的是一些一般的观察。
您的过程包含几个共享公共属性的复杂查询:几乎所有表都基于远程数据库。您无法调整这些查询。
或者说你无法远程调整它们。您需要在本地调整查询,即在表所在的数据库中。调整完查询后,您可以围绕它们构建视图,并在过程中使用这些视图。
事实上,这将是一个很好的起点。分布式查询的性能问题通常是在数据库链接中引入不必要数据的成本。在家庭数据库中过滤数据并仅传输过滤的数据集效率更高。
您极有可能支付此传输费用,因为您要将这些远程表加入本地表allen.alert_main
。所以你需要处理它:要么将它包含在视图中(作为远程表),要么从视图中删除子查询并在过程中引用它。
我认为远程数据库是Oracle Apps系统。这可能会对您允许的操作造成一些限制。
另一种可能的低效率:执行选择多次而不是一次。这......
SELECT NVL (MAX (parent_request_id), 1)
INTO v_parent_id
FROM apps.fnd_concurrent_requests@db_link
WHERE request_id = p_request_id;
SELECT NVL (MAX (last_updated_by), 0)
INTO v_last_updated_by
FROM apps.fnd_concurrent_requests@db_link
WHERE request_id = p_request_id;
......可能是这个......
SELECT NVL (MAX (parent_request_id), 1), NVL (MAX (last_updated_by), 0)
INTO v_parent_id, v_last_updated_by
FROM apps.fnd_concurrent_requests@db_link
WHERE request_id = p_request_id;
虽然这是一个猜测:有时两个单独的读取比组合读取更有效,这取决于索引等。但是你做了很多这样的事情,所以值得研究。
答案 1 :(得分:0)
似乎这个表:apps.fnd_concurrent_requests在此过程中被多次选中。 尝试在程序开始时将相关数据放在WITH子句中,以避免在此表上进行不必要的I / O. 您可以找到有关WITH子句here
的更多信息答案 2 :(得分:0)
DRIVING_SITE提示可用于优化分布式查询。
在此处阅读更多内容:http://docs.oracle.com/cd/B28359_01/server.111/b28286/sql_elements006.htm#autoId9
答案 3 :(得分:0)
在远程数据库上创建或填充临时resuslt表,您也可以使用MV。 将insert语句放入sep过程 不要对每条记录使用提交 在代码中添加了更多注释