Есть ли более быстрый способ слияния 120k записей в неделю в oracle pl / sql? - PullRequest
0 голосов
/ 17 апреля 2020

В базе данных имеется около 120 тыс. Записей, и на основе нескольких функций я вычисляю баллы для всех записей, еженедельно мне приходится обновлять таблицу новыми записями и соответствующими баллами.

Ниже приведена процедура который я использую для объединения данных в таблицу:

create or replace procedure scorecalc
AS
score1 number;
score2 number;
score3 number;
CURSOR cur IS
 SELECT Id_number from tableA;

        r_num cur%ROWTYPE;
BEGIN
  --OPEN cur;
  FOR r_num IN cur
  LOOP
    select functionA(r_num.id_number),functionb(r_num.id_number),functionc(r_num.id_number)  into score1, score2,score3 from dual;
Merge into scores A USING
(Select
 r_num.id_number as ID, score1 as scorea, score2 as scoreb, score3 as scorec, TO_DATE(sysdate, 'DD/MM/YYYY') as scoredate
FROM DUAL) B
ON ( A.ID = B.ID and A.scoredate = B.scoredate)
WHEN NOT MATCHED THEN
INSERT (
 ID, scorea, scoreb, scorec, scoredate)
VALUES (
 B.ID, B.scorea, B.scoreb, B.scorec,B.scoredate)
WHEN MATCHED THEN
UPDATE SET
 A.scorea = B.scorea,
 A.scoreb = B.scoreb,
 A.scorec = B.scorec;
 COMMIT;
  END LOOP;
END;

, тогда как функция A / B / C имеет сложные запросы, присоединяется к ней для вычисления оценки.

Пожалуйста, предложите мне любые способ улучшить производительность, потому что в настоящее время с помощью этого фрагмента кода я могу вставить только 2k записей в течение 1 часа? Могу ли я использовать параллельный DML здесь? Спасибо!

Ответы [ 3 ]

1 голос
/ 17 апреля 2020

Почему вы делаете это в процедуре? Все это можно сделать с помощью DML:

MERGE INTO scores a USING
  (SELECT ta.id_number AS ID, 
          functionA(ta.id) AS scoreA,
          functionB(ta.id) AS scoreB,
          functionC(ta.id) AS scoreC,
          TO_DATE(sysdate, 'DD/MM/YYYY') as scoredate
   FROM tableA ta) b
ON (a.id = b.id AND a.scoredate = b.scoredate)
WHEN MATCHED THEN UPDATE SET
  a.scorea = b.scorea,
  a.scoreb = b.scoreb,
  a.scorec = b.scorec
WHEN NOT MATCHED THEN INSERT (ID, scorea, scoreb, scorec, scoredate)
VALUES (B.ID, B.scorea, B.scoreb, B.scorec,B.scoredate);

Если после этого вы захотите использовать подсказку PARALLEL, не стесняйтесь. Но вам определенно следует избавиться от этого курсора и прекратить выполнять медленную обработку.

0 голосов
/ 18 апреля 2020

Чтобы запланировать это, просто поместите оператор @Del в блок процедуры;

create or replace procedure Saturday_Night_Merge is 
begin 
    <Put the merge statement here> 
end Saturday_Night_Merge;
0 голосов
/ 17 апреля 2020

Что-то, с чем я имел некоторый успех, вставляло из оператора select. Это довольно производительно, поскольку не требует вставки строк за строкой.

В вашем случае, я думаю, это будет что-то вроде:

INSERT INTO table (ID, scorea, scoreb, scorec, scoredate)
SELECT functionA(id_number), functionB(id_number), functionC(id_number)
FROM tableA

Примером этого может быть находится по ссылке ниже: https://docs.oracle.com/cd/B12037_01/appdev.101/b10807/13_elems025.htm

...