Как я могу улучшить производительность этого SQL-запроса? - PullRequest
0 голосов
/ 09 октября 2019

Моя таблица содержит 51 миллион строк данных, состоящих из 500 000 продуктов. Мне нужно получить информацию о продуктах 500 тыс., Например о прилагаемом коде, но в настоящее время это занимает более 30 минут.

Пробовал несколько разных итераций, но может видеть только хорошую производительность, которая ограничивает список продуктов в каждой подпрограмме. select и main select

Фрагмент таблицы:

PNUM | EFFECTIVE_DATE | STAGE | ORG_ID | CURRENT_FLAG
-- | -- | -- | -- | --
2A1245 | 1999-10-01 | 07 | W6 | N
2A1245 | 2006-01-01 | 07 | U4 | N
2A1245 | 2007-11-21 | 07 | U4 | N
2A1245 | 2008-03-23 | 07 | KF | N
2A1245 | 2008-11-23 | 07 | KF | N
2A1245 | 2009-02-25 | 07 | KF | N
2A1245 | 2015-03-19 | 07 | U5 | N
2A1245 | 2015-04-14 | 07 | U6 | N
2A1245 | 2015-04-17 | 07 | U6 | N
2A1245 | 2015-05-01 | 07 | U6 | N
2A1245 | 2017-09-26 | 08 | 8X | N
2A1245 | 2019-02-20 | 08 | 8X | N
2A1245 | 2019-03-18 | 08 | 8X | N
2A1245 | 2019-04-24 | 08 | 8X | N
2A1245 | 2019-04-29 | 08 | 8X | N
2A1245 | 2019-05-11 | 08 | 8X | N
2A1245 | 2019-05-15 | 08 | 8X | N
2A1245 | 2019-06-05 | 08 | 1Z | N
2A1245 | 2019-06-08 | 09 | W1E | N
2A1245 | 2019-06-11 | 09 | W1E | N
2A1245 | 2019-08-19 | 09 | EBI | N
2A1245 | 2019-09-03 | 09 | EBI | Y
SELECT a.PNUM, c.STAGE, MIN(a.EFFECTIVE_DATE) AS NEW_DATE, c.STAGE_CHANGE
FROM D_PRODUCT a
LEFT JOIN (SELECT x.PNUM, x.STAGE FROM D_PRODUCT x 
            WHERE CURRENT_FLAG = 'Y' ) b ON b.PNUM = a.PNUM
LEFT JOIN (SELECT y.PNUM, y.STAGE, MIN(y.EFFECTIVE_DATE) AS STAGE_CHANGE 
          FROM D_PRODUCT y    GROUP BY y.PNUM, y.STAGE) c 
            ON b.PNUM= c.PNUM AND b.STAGE = C.STAGE
  GROUP BY a.PNUM, c.STAGE, c.STAGE_CHANGE

ВЫХОД:

PNUM   | STAGE | NEW_DATE   | STAGE_CHANGE
--     | --    | --         | --
2A1245 | 09    | 1999-10-01 | 2019-06-08

В настоящее время требуется несколько секунд для запуска с ограничением на один продуктили PNUM в пределах каждого дополнительного выбора и основного выбора, но время ожидания истекает через 30 минут или около того, когда не ограничено

Ответы [ 3 ]

0 голосов
/ 09 октября 2019

Использование сопутствующих суб-выборов может помочь вашему исполнению.

WITH D_PRODUCT ( PNUM , EFFECTIVE_DATE , STAGE , ORG_ID , CURRENT_FLAG ) AS (VALUES 
 ('2A1245' , '1999-10-01' , 07 , 'W6' , 'N')
,('2A1245' , '2006-01-01' , 07 , 'U4' , 'N')
,('2A1245' , '2007-11-21' , 07 , 'U4' , 'N')
,('2A1245' , '2008-03-23' , 07 , 'KF' , 'N')
,('2A1245' , '2008-11-23' , 07 , 'KF' , 'N')
,('2A1245' , '2009-02-25' , 07 , 'KF' , 'N')
,('2A1245' , '2015-03-19' , 07 , 'U5' , 'N')
,('2A1245' , '2015-04-14' , 07 , 'U6' , 'N')
,('2A1245' , '2015-04-17' , 07 , 'U6' , 'N')
,('2A1245' , '2015-05-01' , 07 , 'U6' , 'N')
,('2A1245' , '2017-09-26' , 08 , '8X' , 'N')
,('2A1245' , '2019-02-20' , 08 , '8X' , 'N')
,('2A1245' , '2019-03-18' , 08 , '8X' , 'N')
,('2A1245' , '2019-04-24' , 08 , '8X' , 'N')
,('2A1245' , '2019-04-29' , 08 , '8X' , 'N')
,('2A1245' , '2019-05-11' , 08 , '8X' , 'N')
,('2A1245' , '2019-05-15' , 08 , '8X' , 'N')
,('2A1245' , '2019-06-05' , 08 , '1Z' , 'N')
,('2A1245' , '2019-06-08' , 09 , 'W1E' , 'N')
,('2A1245' , '2019-06-11' , 09 , 'W1E' , 'N')
,('2A1245' , '2019-08-19' , 09 , 'EBI' , 'N')
,('2A1245' , '2019-09-03' , 09 , 'EBI' , 'Y')
)

SELECT
    PNUM
,   STAGE
,   (SELECT MIN(EFFECTIVE_DATE) FROM D_PRODUCT M WHERE m.PNUM = a.PNUM) AS EFFECTIVE_DATE
,   (SELECT MIN(EFFECTIVE_DATE) FROM D_PRODUCT C WHERE c.PNUM = a.PNUM AND c.STAGE = a.STAGE ) AS STAGE_CHANGE
FROM D_PRODUCT a
WHERE 
    CURRENT_FLAG = 'Y' 

Возвращает

PNUM      STAGE   EFFECTIVE_DATE  STAGE_CHANGE
------    -----   --------------  ------------
2A1245    9       1999-10-01      2019-06-08
0 голосов
/ 09 октября 2019

Вы можете попробовать следующий SQL.

select b.pnum, max(current_stage) current_stage, 
min(b.effective_date) as new_date,
max(case when b.current_stage = b.stage then b.effective_date else null end) as STAGE_CHANGE
from
(select a.pnum , a.stage , 
min(a.effective_date) as effective_date, 
max(case when a.current_flag = 'Y' then a.stage else null end) as current_stage
from  D_PRODUCT a
group by a.pnum , a.stage) b
group by b.pnum
0 голосов
/ 09 октября 2019

Полагаю, нет необходимости трижды присоединяться к столу. Это может быть достигнуто также с помощью 2-х объединений, что может повысить производительность -

SELECT a.PNUM, c.STAGE, a.EFFECTIVE_DATE, c.STAGE_CHANGE
FROM D_PRODUCT a
LEFT JOIN (SELECT y.PNUM, y.STAGE, MIN(y.EFFECTIVE_DATE) AS STAGE_CHANGE 
           FROM D_PRODUCT y
           GROUP BY y.PNUM, y.STAGE) c ON a.PNUM= c.PNUM AND a.STAGE = c.STAGE

После этого у вас может быть составной индекс на (PNUM, STAGE)

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