Обновить запрос для оптимизации - PullRequest
0 голосов
/ 07 февраля 2019

Может ли следующий запрос быть переписан?Я думаю, что Merge улучшит производительность.пожалуйста, посоветуйте и помогите мне переписать его лучше

Update table1 
Set Tgt_col ='2'
where col1 in (
SELECT  ls.col1
 FROM table1 ls 
WHERE ls. Col2 ||ls. col3||ls.col22||To_Char(ls.time_col,'YYYYMMDD') IN (
  SELECT  o1. Col2||o1. col3||o1. col22||To_Char(o1. time_col,'YYYYMMDD')
  FROM table1 o1
  INNER JOIN table1 o2 ON o1. Col2 = o2. Col2
  WHERE o1. col3<> o2. col3
  AND  Nvl(o1. col22, 'XX') = Nvl(o2. col22, 'XX')
  AND To_Char(o1. time_col,'YYYYMMDD') = To_Char(o2. time_col,'YYYYMMDD')
  AND o1.date_col = :A
  AND o2. date_col = :A
  AND o1.col10 = o2.col10
  AND o1.col4 IN ('A','B','C')
  AND o1.is_root=0 AND o1.is_leaf=1
  AND o2. col4 IN ('A','B','C')
  AND o2.is_root=0 AND o2.is_leaf=1
  AND o1.col5 IN ('US','CA')
  AND o2.col5 IN ('US','CA')
GROUP BY o1. Col2||o1. col3||o1. col22||To_Char(o1. time_col,'YYYYMMDD')
)
AND ls. col4 IN ('A','B','C')
AND ls.tgt_col IS NULL
AND ls. date_col = :A
AND ls.col5 IN ('US','CA')
AND ls.ID1 IN (SELECT ID1 FROM table2 F
                                          WHERE F.col6 IN (SELECT col6  FROM table3
                                                               WHERE date_col =:A AND col7 = 1 )
                                                                                                                AND F.col8 = '1')
);

Ответы [ 2 ]

0 голосов
/ 07 февраля 2019

При отсутствии данных для тестирования, я думаю, что следующее будет быстрее, чем ваш текущий запрос:

UPDATE table1
SET    tgt_cl = '2'
WHERE  col1 IN (SELECT col1
                FROM   (SELECT o1.col1,
                               o1.col2,
                               o1.col3,
                               o1.col22,
                               o1.time_col,
                               COUNT(DISTINCT o1.col3) OVER (PARTITION BY o1.col2, o1.col3, o1.time_col, o1.col10, o1.col22) dcnt
                        FROM   table1 o1
                        WHERE  o1.date_col = :a
                        AND    o1.col4 IN ('A', 'B', 'C')
                        AND    o1.is_root = 0
                        AND    o1.is_leaf = 1
                        AND    o1.col5 IN ('US', 'CA')
                        AND    o1.col3 IS NOT NULL)
                WHERE  dcnt > 1
                AND    id1 IN (SELECT id1
                               FROM   table2 f
                               WHERE  f.col6 IN (SELECT col6
                                                 FROM   table3
                                                 WHERE  date_col = :a
                                                 AND    col17 = 1)
                               AND    f.col8 = '1'));

Похоже, вы пытаетесь найти значения col1 в таблице1, которые имеют несколько различныхЗначения col3 для каждой комбинации col2, col3, time_col, col10 и col22, поэтому я использовал функцию аналитического подсчета, чтобы выяснить это.Вы можете найти EXISTS лучше, чем IN здесь;Вы должны проверить, что a) мой запрос работает и b) быстрее ли заменить IN на EXISTS для ваших данных или нет.

0 голосов
/ 07 февраля 2019

Попробуйте следующий код, он должен быть быстрее:

UPDATE table1
   SET Tgt_col = '2'
 WHERE EXISTS (SELECT 1
                 FROM table1 ls
                 JOIN table2 F
                   ON (f.ID1 = ls.ID1)
                 JOIN table3 t3
                   ON (t3.col6 = F.col6
                       -- IF :A is always inserted, you can remove if-null checkings for this date_col
                       AND (   (t3.date_col is null AND ls.date_col is null)
                            OR t3.date_col = ls.date_col
                            )
                       )
                WHERE ls.col1 = table1.col1
                  AND EXISTS (SELECT 1
                                FROM table1 o1
                                JOIN table1 o2 
                                  ON (o1.Col2 = o2.Col2
                                      AND o1.col10 = o2.col10
                                      AND o1.is_root = o2.is_root
                                      AND o1.is_leaf = o2.is_leaf
                                      AND (   (o1.time_col is null AND o2.time_col is null)
                                           OR o1.time_col = o2.time_col
                                           )
                                      AND (   (o1.col22 is null AND o2.col22 is null)
                                           OR o1.col22 = o2.col22
                                           )
                                      -- IF :A is always inserted, you can remove if-null checkings for date_col
                                      AND (   (o1.date_col is null AND o2.date_col is null)
                                           OR o1.date_col = o2.date_col
                                           )
                                      AND o1.col3 != o2.col3)
                               WHERE     (o1.Col2 = ls.Col2 OR (o1.Col2 is null AND ls.Col2 is null))
                                     AND (o1.col3 = ls.col3 OR (o1.col3 is null AND ls.col3 is null))
                                     AND (o1.col22 = ls.col22 OR (o1.col22 is null AND ls.col22 is null))
                                     AND (o1.time_col = ls.time_col OR (o1.time_col is null AND ls.time_col is null))
                                     -- IF :A is always inserted, you can remove if-null checkings for this date_col
                                     AND (o1.date_col = ls.date_col OR (o1.date_col is null AND ls.date_col is null))
                                     AND o1.is_root = 0
                                     AND o1.is_leaf = 1
                                     -- IF o1.col4 should be equal to o2.col4 THEN also add it inside `ON` and remove one of two from here
                                     AND o1.col4 IN ('A', 'B', 'C')
                                     AND o2.col4 IN ('A', 'B', 'C')
                                     -- IF o1.col5 should be equal to o2.col5 THEN also add it inside `ON` and remove one of two from here
                                     AND o1.col5 IN ('US', 'CA')
                                     AND o2.col5 IN ('US', 'CA')
                                     AND rownum = 1)
                  -- IF ls.col4 should be equal to col4 from inside the subquery THEN add it inside as, for example, for col22
                  AND ls.col4 IN ('A', 'B', 'C')
                  AND ls.tgt_col IS NULL
                  AND ls.date_col = :A
                  -- IF ls.col5 should be equal to col5 from inside the subquery THEN add it inside as, for example, for col22
                  AND ls.col5 IN ('US', 'CA')
                  AND F.col8 = '1'
                  AND t3.col7 = 1
                  AND rownum = 1);

Основные различия:

  • Удаление конкатенации и добавление ее по сравнению сзначения в выражении where
  • Использование EXISTS с rownum вместо IN
  • Использование JOIN вместо IN для table2 F и table3сравнения

Если col1 является уникальным ключом, запишите все проверки ls table во внешнем запросе (ls.col4 IN ('A', 'B', 'C') AND ls.tgt_col IS NULL AND ls.date_col = :A AND ls.col5 IN ('US', 'CA')), чтобы уменьшить количество строк, проходящих проверку EXISTS.

В коде есть и другие советы в комментариях.

Всегда проверяйте изменения данных перед фиксацией

Надеюсь, я помог!

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