SQL查询(带有子查询,分组和排序依据)优化

时间:2018-11-19 10:52:08

标签: sql query-optimization

请帮助我优化以下语句。当处理大量数据(在我的情况下为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 :(得分:0)

第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列是唯一的)