как сократить или оптимизировать запрос JOIN в postgres - PullRequest
0 голосов
/ 29 февраля 2020

Я получил следующий запрос, в котором я присоединяюсь 4 раза. Но для возврата результата требуется много времени. Есть ли способ оптимизировать этот запрос?

    SELECT T1.wbd_date as WBD_DATE,  to_char(T1.wbd_block_no, 'fm00') as BLOCK_NO, T2.wbd_value as AmbHum, T3.wbd_value as AmbTemp,
T4.wbd_value as SWT, T5.wbd_value as Expval
FROM (
SELECT wbd_attribute_id, wbd_date, wbd_block_no, wbd_value 
FROM wb_block_data ) T1 
JOIN wb_block_data T2 on T1.wbd_date = T2.wbd_date AND T1.wbd_block_no = T2.wbd_block_no and T2.wbd_attribute_id = 152112 and to_char(T2.wbd_date,'MM YYYY')='07 2019'
JOIN wb_block_data T3 on T1.wbd_date = T3.wbd_date AND T1.wbd_block_no = T3.wbd_block_no and T3.wbd_attribute_id = 152116 and to_char(T3.wbd_date,'MM YYYY')='07 2019'
JOIN wb_block_data T4 on T1.wbd_date = T4.wbd_date AND T1.wbd_block_no = T4.wbd_block_no and T4.wbd_attribute_id = 152120 and to_char(T4.wbd_date,'MM YYYY')='07 2019'
JOIN wb_block_data T5 on T1.wbd_date = T5.wbd_date AND T1.wbd_block_no = T5.wbd_block_no and T5.wbd_attribute_id = 150661 and to_char(T5.wbd_date,'MM YYYY')='07 2019'

Ответы [ 3 ]

1 голос
/ 29 февраля 2020

Вы, по сути, делаете сводку, поскольку использование условной агрегации может быть быстрее:

select wbd_attribute_id, block_no, wbd_date,
       max(wbd_value) filter (where wbd_attribute_id = 152112) as AmbHum,
       max(wbd_value) filter (where wbd_attribute_id = 152116) as AmbTemp,
       max(wbd_value) filter (where wbd_attribute_id = 152120) as swt,
       max(wbd_value) filter (where wbd_attribute_id = 152120) as Expval
from (
  SELECT wbd_attribute_id, wbd_date, to_char(wbd_block_no, 'fm00') as block_no, wbd_value 
  FROM wb_block_data 
  where wbd_attribute_id in (152112, 152116, 152120, 150661)
    and wbd_date >= DATE '2019-07-01' 
    and wbd_date < DATE '2019-08-01'
) t
group by wbd_attribute_id, wbd_date, block_no

Для этого требуется индекс (wbd_attribute_id, wbd_date).

0 голосов
/ 03 марта 2020

Я изменил запрос на этот, и с этим я быстро получаю желаемый результат

SELECT T1.wbd_date as WBD_DATE,  to_char(T1.wbd_block_no, 'fm00') as BLOCK_NO, T2.wbd_value as AmbHum, T3.wbd_value as AmbTemp,
T4.wbd_value as SWT, T5.wbd_value as Expval
FROM (
SELECT wbd_attribute_id, wbd_date, wbd_block_no, wbd_value 
FROM wb_block_data where to_char(wbd_date,'MM YYYY')='07 2019') T1 
JOIN wb_block_data T2 on T1.wbd_date = T2.wbd_date AND T1.wbd_block_no = T2.wbd_block_no and T2.wbd_attribute_id = 152112 
JOIN wb_block_data T3 on T1.wbd_date = T3.wbd_date AND T1.wbd_block_no = T3.wbd_block_no and T3.wbd_attribute_id = 152116 
JOIN wb_block_data T4 on T1.wbd_date = T4.wbd_date AND T1.wbd_block_no = T4.wbd_block_no and T4.wbd_attribute_id = 152120 
JOIN wb_block_data T5 on T1.wbd_date = T5.wbd_date AND T1.wbd_block_no = T5.wbd_block_no and T5.wbd_attribute_id = 150661 
0 голосов
/ 29 февраля 2020

Может работать такой индекс, как:

CREATE INDEX idx ON wb_block_data (wbd_date, wbd_block_no, wbd_attribute_id);

Однако нам также необходимо разрешить условия соединения:

SELECT T1.wbd_date as WBD_DATE, to_char(T1.wbd_block_no, 'fm00') as BLOCK_NO, T2.wbd_value as AmbHum, T3.wbd_value as AmbTemp, T4.wbd_value as SWT, T5.wbd_value as Expval
FROM
(
    SELECT wbd_attribute_id, wbd_date, wbd_block_no, wbd_value 
    FROM wb_block_data
) T1 
JOIN wb_block_data T2 on T1.wbd_date = T2.wbd_date AND T1.wbd_block_no = T2.wbd_block_no and T2.wbd_attribute_id = 152112 and T2.wbd_date >= '2019-07-01' and T2.wbd_date < '2019-08-01'
JOIN wb_block_data T3 on T1.wbd_date = T3.wbd_date AND T1.wbd_block_no = T3.wbd_block_no and T3.wbd_attribute_id = 152116 and T3.wbd_date >= '2019-07-01' and T3.wbd_date < '2019-08-01'
JOIN wb_block_data T4 on T1.wbd_date = T4.wbd_date AND T1.wbd_block_no = T4.wbd_block_no and T4.wbd_attribute_id = 152120 and T4.wbd_date >= '2019-07-01' and T4.wbd_date < '2019-08-01'
JOIN wb_block_data T5 on T1.wbd_date = T5.wbd_date AND T1.wbd_block_no = T5.wbd_block_no and T5.wbd_attribute_id = 150661 and T5.wbd_date >= '2019-07-01' and T5.wbd_date < '2019-08-01';

Единственное изменение, которое я сделал в вашем запрос был express требование даты как диапазон, без использования to_char:

wbd_date >= '2019-07-01' and wbd_date < '2019-08-01'

Это sargable , что означает, что Postgres может использовать индекс для столбец wbd_date для удовлетворения диапазона дат июля 2019 года.

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