Проблема производительности - PL / SQL извлекает курсор к таблице записей с массовым сбором - PullRequest
0 голосов
/ 26 февраля 2019

Я хочу обработать большое количество записей, и я использую инструкцию массового сбора для извлечения данных в таблицу записей.Тем не менее, я уверен, что есть более адекватный способ достичь того, что я ищу.Вот код:

  FUNCTION GET_STORE_ITEMS(I_store           IN   STORE.STORE%TYPE,
                           I_item_status     IN   WIN_STORE.STATUS%TYPE,
                           ----------- output ------------
                           O_item_data       OUT  NB_TAB_ITEM_DETAIL,
                           ----------- error -------------
                           O_error_message   OUT  VARCHAR2)
  RETURN BOOLEAN IS
    -- ----------------------------------
    --            VARIABLES            --
    -- ----------------------------------
    L_program         VARCHAR2(100)     := 'NB_ITEM_INFO_SQL.GET_ITEM_DETAIL';
    L_error_message   VARCHAR2(500)     := '';
    --
    -- ----------------------------------
    --            CURSORS              --
    -- ----------------------------------
     -- 003 begin
  CURSOR C_get_info IS
   -- #004 - begin
     SELECT NB_REC_ITEM_DETAIL(sku, desc_up, system_ind, status, division, div_name, group_no, group_name,
                               dept, dept_name, class, class_name, subclass, sub_name, nb_var_weight,
                              (SELECT upc as primary_ean
                                 FROM upc_ean u
                                WHERE u.sku = tab.sku
                                  AND u.primary_upc_ind = 'Y'
                                  AND rownum = 1),
                              CAST( multiset(SELECT u.upc
                                               FROM upc_ean u
                                              WHERE u.sku = tab.sku
                                                AND u.primary_upc_ind <> 'Y')
                                    AS NB_TAB_ITEM_EAN )
                               )
      FROM (SELECT info.sku,
                   info.desc_up,
                   info.nb_var_weight,
                   info.system_ind,
                   info.status,
                   div.division,
                   div.div_name,
                   c.group_no,
                   b.group_name,
                   info.dept,
                   c.dept_name,
                   info.class,
                   a.class_name,
                   info.subclass,
                   e.sub_name
            FROM (SELECT w.store,
                         w.sku,
                         nvl(wa.nb_var_weight, 'N') nb_var_weight,
                         w.status,
                         ts.desc_up,
                         ts.system_ind,
                         ts.dept,
                         ts.class,
                         ts.subclass
                    FROM win_store w,
                         win_attributes wa,
                         desc_look ts,
                         deps d
                   WHERE w.sku  = wa.sku
                     AND w.store = I_store
                     AND wa.sku = ts.sku
                  --   AND (w.status = I_item_status OR I_item_status IS NULL)
                     AND d.dept = ts.dept
                 UNION ALL
                  SELECT st.store,
                         st.sku,
                         'N' nb_var_weight,
                         st.status,
                         ts.desc_up,
                         ts.system_ind,
                         ts.dept,
                         ts.class,
                         ts.subclass
                    FROM rag_skus_st st,
                         desc_look ts,
                         deps d
                   WHERE st.store = I_store
                     AND ts.sku = st.sku
                 --    AND (st.status = I_item_status OR I_item_status IS NULL)
                     AND d.dept = ts.dept
                 UNION ALL
                  SELECT ps.store,
                         ps.pack_no,
                         'N' nb_var_weight,
                         ps.status,
                         ts.desc_up,
                         ts.system_ind,
                         ts.dept,
                         ts.class,
                         ts.subclass
                    FROM packstore ps,
                         desc_look ts,
                         deps d
                   WHERE ps.store = I_store
                     AND ps.pack_no = ts.sku
                  --   AND (ps.status = I_item_status OR I_item_status IS NULL)
                     AND d.dept = ts.dept
                  )info,
                  deps c,
                  groups b,
                  division div,
                  class a,
                  subclass e
              WHERE c.dept = info.dept
                AND b.group_no = c.group_no
                AND div.division = b.division
                AND a.dept = info.dept
                AND a.class = info.class
                AND e.dept = info.dept
                AND e.class = info.class
                AND e.subclass = info.subclass
   ) tab;
    --
  BEGIN
    --
    -- Instantiate output structure object.
    --
    O_item_data := NB_TAB_ITEM_DETAIL();
    --
    OPEN C_get_info;
    FETCH C_get_info BULK COLLECT INTO O_item_data;
    CLOSE C_get_info;
    --
    RETURN TRUE;
    --
  EXCEPTION
    --
    WHEN OTHERS THEN
      --
      IF C_get_info%ISOPEN THEN
        --
        CLOSE C_get_info;
        --
      END IF;
      --
      O_error_message := SQL_LIB.CREATE_MSG('PACKAGE_ERROR',
                                            SQLERRM,
                                            L_program,
                                            TO_CHAR(SQLCODE));
      RETURN FALSE;
      --
    --
  END GET_STORE_ITEMS;

В худшем случае количество возвращаемых строк составляет ~ 1,4 миллиона.Можно ли как-нибудь повысить производительность запроса для такого большого количества записей?Или я должен попробовать другой подход при извлечении данных в структуру вывода?Заранее спасибо.

1 Ответ

0 голосов
/ 01 марта 2019

Я на самом деле решил проблему, добавив нумерацию страниц.Как сказал в комментариях Джон Хеллер, это не проблема производительности, связанная с кодом PL / SQL.Из-за большого количества записей, возвращаемых функцией, необходимо контролировать, сколько данных она должна вернуть при вызове.Исходя из этого, я улучшил курсор, чтобы ограничить возвращаемое подмножество данных, и оптимизировал запрос в попытке снизить его стоимость.Я также ввел нумерацию страниц и определил предел записей в 1000.

FUNCTION GET_STORE_ITEMS(I_store           IN   STORE.STORE%TYPE,
                         I_item_status     IN   WIN_STORE.STATUS%TYPE,
                         --------- pagination ----------
                         I_offset          IN   PLS_INTEGER  DEFAULT NULL,
                         I_limit           IN   PLS_INTEGER  DEFAULT NULL,
                         O_total_reg       OUT  PLS_INTEGER,
                         ----------- output ------------
                         O_item_data       OUT  SYS_REFCURSOR,
                         ----------- error -------------
                         O_error_message   OUT  VARCHAR2)
  RETURN BOOLEAN IS
    --
    L_error_message    VARCHAR2(500)     := '';
    L_skip             PLS_INTEGER       := I_offset;
    L_take             PLS_INTEGER       := I_limit;
    L_limit_take       PLS_INTEGER       := 1000;
    L_tab_item_detail  NB_TAB_ITEM_DETAIL := NB_TAB_ITEM_DETAIL();
    --
    CURSOR C_get_total_rec IS
      --
      SELECT COUNT(1)
        FROM (
              -- based on the main query --
              -- ...
              );
    -- Get store items information.
    CURSOR C_get_info IS
      --
      SELECT NB_REC_ITEM_DETAIL(sku            => sku,
                                item_desc      => desc_up,
                                system_ind     => system_ind,
                                status         => status,
                                div_no         => division,
                                div_desc       => div_name,
                                group_no       => group_no,
                                group_desc     => group_name,
                                dept_no        => dept,
                                dept_desc      => dept_name,
                                class_no       => class,
                                class_desc     => class_name,
                                subclass_no    => subclass,
                                subclass_desc  => sub_name,
                                var_weight_ind => nb_var_weight,
                                primary_ean    => (SELECT upc as primary_ean
                                                     FROM upc_ean u
                                                    WHERE u.sku = tab.sku
                                                      AND u.primary_upc_ind = 'Y'
                                                      AND rownum = 1)
                               )
        FROM ( -- main query --
              -- ...
              ) tab
          WHERE ROWNUM <= L_skip + L_take;
    --
  BEGIN
    -- get the total number of records.
    OPEN C_get_total_rec;
    FETCH C_get_total_rec INTO O_total_reg;
    CLOSE C_get_total_rec;

    -- Set the pagination parameters to get all records by default.
    IF L_skip IS NULL OR L_skip < 0 THEN
      --
      L_skip := 0; -- setting offset to 0
      --
    END IF;
    --
     IF L_take > L_max_take OR L_take < 0 OR L_take IS NULL THEN
        --
        L_take := L_max_take;
        --
      END IF;
    --
    OPEN C_get_info;
    FETCH C_get_info BULK COLLECT INTO L_tab_item_detail LIMIT 1000;
    CLOSE C_get_info;
    --
    -- Open item data sys_refcursor.
    --
    OPEN O_item_data for
      --
      SELECT *
        FROM TABLE(L_tab_item_detail);
    --
    RETURN TRUE;
    --
  EXCEPTION
    --
    WHEN OTHERS THEN
      --
      -- ...
      --
      RETURN FALSE;
      --
    --
  END GET_STORE_ITEMS;

Спасибо всем!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...