Оптимизация SQL-запросов (с подзапросом, группированием и упорядочением по) - PullRequest
0 голосов
/ 19 ноября 2018

Вы можете помочь мне оптимизировать следующее утверждение. Он имеет плохую производительность при работе с огромным объемом данных (в моем случае 3Mio Messages и 25Mio MessageWorkItems).

У кого-нибудь есть предложения? Заранее спасибо.

select distinct msg.id,  msgWorkItem_1.description
from message msg 
left outer join message_work_item msgWorkItem_1 on msg.id=msgWorkItem_1.message_id 
and (   msgWorkItem_1.id in (
        select max(msgWorkItem_2.id) 
        from message_work_item msgWorkItem_2 
        inner join message_work_item_type msgWorkItem_Type on msgWorkItem_2.message_work_item_type_id=msgWorkItem_Type.id 
        where 
            msgWorkItem_2.creation_type= 'mobile'
            and msgWorkItem_2.description is not null 
            and msgWorkItem_Type.code <> 'sent-to-app-manually' 
        --  Is it possible to avoid this correlation to the outer query ? )
            and msgWorkItem_2.message_id = msg.id)
        ) 
where msg.deactivation_time > ? 
order by msgWorkItem_1.description asc

1 Ответ

0 голосов
/ 19 ноября 2018

ШАГ 1: Выложите запрос, чтобы у меня была надежда его прочитать

SELECT
  DISTINCT
  msg.id,
  msgWorkItem_1.description
FROM
  message msg 
LEFT OUTER JOIN
  message_work_item   AS msgWorkItem_1
    ON  msgWorkItem_1.message_id = msg.id 
    AND msgWorkItem_1.id =
        (
          SELECT
            MAX(msgWorkItem_2.id) 
          FROM
            message_work_item      AS msgWorkItem_2 
          INNER JOIN
            message_work_item_type AS msgWorkItem_Type
              ON msgWorkItem_2.message_work_item_type_id=msgWorkItem_Type.id 
          WHERE
                msgWorkItem_2.creation_type= 'mobile'
            AND msgWorkItem_2.description IS NOT NULL 
            AND msgWorkItem_Type.code <> 'sent-to-app-manually' 
            --  Is it possible to avoid this correlation to the outer query ?
            AND msgWorkItem_2.message_id = msg.id
        )
WHERE
  msg.deactivation_time > ? 
ORDER BY
  msgWorkItem_1.description ASC

ШАГ 2: переписать, используя аналитические функции вместо MAX ()

SELECT
  DISTINCT
  message.id,
  message_work_item_sorted.description
FROM
  message
LEFT OUTER JOIN
(
  SELECT
    message_work_item.message_id,
    message_work_item.description,
    ROW_NUMBER() OVER (PARTITION BY message_work_item.message_id
                           ORDER BY message_work_item.id DESC
                      )
                         AS row_ordinal
  FROM
    message_work_item
  INNER JOIN
    message_work_item_type
      ON message_work_item.message_work_item_type_id = message_work_item_type.id 
  WHERE
        message_work_item.creation_type= 'mobile'
    AND message_work_item.description IS NOT NULL 
    AND message_work_item_type.code <> 'sent-to-app-manually' 
)
  message_work_item_sorted
    ON  message_work_item_sorted.message_id  = message.id
    AND message_work_item_sorted.row_ordinal = 1
WHERE
  message.deactivation_time > ? 
ORDER BY
  message_work_item_sorted.description ASC

Имея больше информации, мы, вероятно, могли бы помочь в дальнейшем, но поскольку вы не дали определения таблицам, ограничениям или бизнес-логике, это всего лишь переписывание того, что вы уже реализовали.

Например, я сильно сомневаюсь, что вам нужен DISTINCT (при условии, что столбцы id в ваших таблицах уникальны) .

...