提高PL / SQL的性能

时间:2013-06-25 17:01:10

标签: sql oracle plsql oracle11g oracle9i

我编写了一个在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;
/

有没有办法提高这项计划的效率?

4 个答案:

答案 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过程 不要对每条记录使用提交 在代码中添加了更多注释