как да стартирате съхранената процедура в пакетен режим или в паралелна обработка

Ние итерираме 100k+ записа от глобалната временна таблица. Съхранената процедура по-долу ще итерира всички записи от glogal temp table един по един и трябва да обработи под три стъпки.

  1. за да видите дали продуктът съществува или не
  2. за да видите дали продуктът в активите има „категория“ или не.
  3. за да видите дали имената на активите започват с „%pdf%“ или не.

Така че всеки запис трябва да обработи тези 3 стъпки и окончателните имена на документи ще бъдат съхранени в таблицата за успешния запис. Ако възникне грешка в някоя от стъпките, съобщението за грешка ще бъде съхранено за този запис.

По-долу съхранената процедура отнема много време за обработка, тъй като нейната обработка е последователна.

  1. Има ли някакъв начин да направите този процес по-бърз в самата съхранена процедура, като извършите партиден процес?
  2. Ако не е възможно в съхранена процедура, тогава можем ли да променим този код в Java и да изпълним този код в многонишков режим? като създаване на 10 нишки и всяка нишка ще вземе един запис едновременно и ще обработи този код. Ще се радвам, ако някой даде някакъв псевдо код.

кой подход ще предложи?

DECLARE
V_NODE_ID  VARCHAR2(20);
V_FILENAME VARCHAR2(100);
V_CATEGORY_COUNT INTEGER :=0;  
FINAL_FILNAME VARCHAR2(2000);
V_FINAL_ERRORMESSAGE VARCHAR2(2000);


CURSOR C1 IS
SELECT isbn FROM GT_ADD_ISBNS GT;

CURSOR C2(v_isbn in varchar2) IS
SELECT ANP.NODE_ID NODE_ID
        FROM 
        table1 ANP,
        table2 ANPP,
        table3 AN
        WHERE 
      ANP.NODE_ID=AN.ID AND
    ANPP.NODE_ID=ANP.NODE_ID AND
    AN.NAME_ID =26 AND
    ANP.CATEORGY='category' AND
    ANP.QNAME_ID='categories'  AND
        ANP.NODE_ID IN(SELECT CHILD_NODE_ID 
                  FROM TABLE_ASSOC START WITH PARENT_NODE_ID IN(v_isbn) 
                      CONNECT BY PRIOR CHILD_NODE_ID = PARENT_NODE_ID);


BEGIN
--Iterating all Products
FOR R1 IN C1 
LOOP

FINAL_FILNAME :='';
BEGIN


--To check whether Product is exists or not
SELECT AN.ID INTO V_NODE_ID 
FROM TABLE1 AN,
TABLE2 ANP
WHERE
AN.ID=ANP.NODE_ID AND
ANP.VALUE in(R1.ISBN);


V_CATEGORY_COUNT :=0;
V_FINAL_ERRORMESSAGE :='';

--To check Whether Product inside the assets are having the 'category' is applied or not
FOR R2 IN C2(R1.ISBN) 
LOOP

V_CATEGORY_COUNT := V_CATEGORY_COUNT+1;  

BEGIN
--In this Logic Product inside the assets have applied the 'category' But those assets are having documents LIKE '%pdf%' or not
SELECT ANP.STRING_VALUE  into V_FILENAME
        FROM 
        table1 ANP,
        table2 ANPP,
        table3 ACD
        WHERE 
       ANP.QNAME_ID=21  AND 
       ACD.ID=ANPP.LONG_VALUE 
       ANP.NODE_ID=ANPP.NODE_ID AND
       ANPP.QNAME_ID=36 AND
       ANP.STRING_VALUE LIKE '%pdf%'  AND 
       ANP.NODE_ID=R2.NODE_ID; 

    FINAL_FILNAME := FINAL_FILNAME  || V_FILENAME ||',';

   EXCEPTION WHEN
     NO_DATA_FOUND THEN
     V_FINAL_ERRORMESSAGE:=V_FINAL_ERRORMESSAGE|| 'Category is applied for this Product But for the asset:'||  R2.NODE_ID || ':Documents[LIKE %pdf%] were not found ;';
     UPDATE GT_ADD_ISBNS SET ERROR_MESSAGE=  V_FINAL_ERRORMESSAGE  WHERE ISBN= R1.ISBN;


     END;--Iterating for each NODEID

END LOOP;--Iterating the assets[Nodes] for each product of catgeory

  --  DBMS_OUTPUT.PUT_LINE('R1.ISBN:' || R1.ISBN ||'::V_CATEGORY_COUNT:' || V_CATEGORY_COUNT);

 IF(V_CATEGORY_COUNT  = 0) THEN
     UPDATE GT_ADD_ISBNS SET ERROR_MESSAGE=  'Category is not applied to none of the Assets for this Product'  WHERE ISBN= R1.ISBN;
   END IF;  


EXCEPTION WHEN
NO_DATA_FOUND THEN
      UPDATE GT_ADD_ISBNS SET ERROR_MESSAGE=   'Product is not Found:' WHERE ISBN= R1.ISBN;
END;

  -- DBMS_OUTPUT.PUT_LINE( R1.ISBN || 'Final documents:'||FINAL_FILNAME);
      UPDATE GT_ADD_ISBNS SET FILENAME=FINAL_FILNAME WHERE ISBN= R1.ISBN;

COMMIT;
END LOOP;--looping gt_isbns
END;

person user739115    schedule 20.02.2018    source източник
comment
Добавете допълнителна колона за части към временната таблица и присвоете номера 1-10 на всички записи по кръгов начин. Променете съхранената процедура, така че да обработва само 1 част. Сега стартирайте съхранена процедура 10 пъти паралелно за всяка част.   -  person Andreas    schedule 20.02.2018
comment
Още по-добре, настройте своя SQL. Обработката на 100k+ записа не трябва да отнема много време за обработка, въпреки че не определяте какво означава дълго.   -  person Andreas    schedule 20.02.2018
comment
отнема 15-16 часа, за да завърши този процес. Моля, имайте предвид, че логиката на заявката е правилна и използва необходимите съединения и необходимите индекси са там в колоните. След добавяне на част от колоната и добавяне на числа. Трябва ли да променя нещо в съхранената процедура?   -  person user739115    schedule 20.02.2018


Отговори (1)


Имате редица потенциални успехи в представянето. Ето един:

„Итерираме 100k+ записа от глобалната временна таблица“

Глобалните временни таблици могат да бъдат доста бавни. Попълването им означава запис на всички тези данни на диск; четене от тях означава четене от диск. Това е много I/O, което може да бъде избегнато. Освен това GTT използват временното таблично пространство, така че може да се конкурирате с други сесии, извършващи големи сортове.

Ето още един червен флаг:

FOR R1 IN C1 LOOP
... FOR R2 IN C2(R1.ISBN) LOOP

SQL е базиран език. Той е оптимизиран за свързване на таблици и връщане на набори от данни по високоефективен начин. Вложените цикли на курсора означават обработка ред по ред, която несъмнено е по-лесна за кодиране, но може да бъде с порядъци по-бавна от еквивалентната операция за набор.

--To check whether Product is exists or not

Имате няколко заявки за избор от едни и същи таблици (AN, 'ANP) using the same criteria (isbn`). Може би всички тези дубликати са единственият начин за валидиране на вашите бизнес правила, но изглежда малко вероятно.

FINAL_FILNAME := FINAL_FILNAME || V_FILENAME ||',';

Може би бихте могли да пренапишете вашата заявка, за да използвате listagg() вместо да използвате процедурна логика за свързване на низ?

UPDATE GT_ADD_ISBNS

Отново, всичките ви актуализации са операции с един ред вместо зададени.

„Има ли някакъв начин да направите този процес по-бърз в самата съхранена процедура, като извършвате пакетен процес?“

Без да знаем вашите правила и контекста, не можем да пренапишем вашата логика вместо вас, но 15-16 часа са твърде много за това, така че определено можете да намалите изминалото време.

Неща, които трябва да имате предвид:

  1. Заменете писането и четенето във временната таблица със заявката, която използвате, за да я попълните
  2. Пренапишете циклите, за да използвате BULK COLLECT с висок ЛИМИТ (напр. 1000), за да подобрите ефективността на избора. Научете повече.
  3. Попълнете масиви и използвайте FORALL, за да подобрите ефективността на актуализациите. Научете повече.
  4. Опитайте се да премахнете всички тези отделни търсения, като включите логиката в основната заявка, като използвате синтаксис OUTER JOIN, за да тествате за съществуване.

Всичко това са предположения. Ако наистина искате да знаете къде процедурата прекарва времето си - и това знание е в основата на всяка успешна настройка, така че трябва да искате да знаете - трябва да стартирате процедурата под PL/SQL Profiler. Това ще ви каже кои линии струват най-много време и обикновено това са тези, върху които трябва да съсредоточите усилията си за настройка. Ако все още нямате достъп до DBMS_PROFILER, ще ви трябва DBA, за да изпълни инсталационния скрипт вместо вас. Научете повече.

"можем ли да променим този код в Java и да стартираме този код в многонишков режим?"

Като се има предвид, че една от причините за забавяне на процедурата е входно-изходната цена за избор от временната таблица, има добър шанс многонишковостта да въведе допълнително съревнование и всъщност да влоши нещата. Първо трябва да подобрите съхранената процедура.

person APC    schedule 20.02.2018