0

我编写了一个在 Oracle 9i 中运行的 PL/SQL 块,它通过 DB 链接处理来自 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

4 回答 4

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;

虽然这是一个猜测:有时两个单独的读取比组合读取更有效,这取决于索引等。但是你经常做那种事情,所以值得研究。

于 2013-06-26T08:25:52.800 回答
0

似乎该表:apps.fnd_concurrent_requests 在此过程中被多次选中。尝试在过程开始时将相关数据放在 WITH 子句中,以避免对该表进行不必要的 I/O。您可以在此处找到有关 WITH 子句的更多信息

于 2013-06-26T05:20:59.130 回答
0

DRIVING_SITE 提示可用于优化分布式查询。

在这里阅读更多:http: //docs.oracle.com/cd/B28359_01/server.111/b28286/sql_elements006.htm#autoId9

于 2013-06-27T07:50:19.053 回答
0

在远程数据库上创建或填充临时结果表,您也可以使用 MV。将插入语句放入 sep 过程中 不要为每条记录使用提交 在代码中添加更多注释

于 2013-11-11T16:45:20.263 回答