【问题标题】:Bad performance of SQL query due to ORDER BY clause and inner join由于 ORDER BY 子句和内部联接,SQL 查询性能不佳
【发布时间】:2015-12-07 11:31:30
【问题描述】:

我有一个查询将 2 个表连接 8 次,每个表在 WHERE 子句中有很多条件。该查询还包括数字列上的ORDER BY 子句。返回需要 12 秒,这太长了,我需要加快速度。令人惊讶的是,我发现如果我删除 ORDER BY 子句需要 2 秒。为什么 order by 会产生如此巨大的差异以及如何对其进行优化?我正在使用 SQL Server 2008 R2。非常感谢。

select top 1   
 cq.answer                              AS RM_comment
,su.user_name                           AS RM_name
,cq.execution_date                      AS RM_date

,cq1.answer                             AS UHB_comment
,su1.user_name                          AS UHB_name
,cq1.execution_date                     AS UHB_date

,cq2.answer                             AS HB_comment
,su2.user_name                          AS HB_name
,cq2.execution_date                     AS HB_date

,cq3.answer                             AS UHCR_comment
,su3.user_name                          AS UHCR_name
,cq3.execution_date                     AS UHCR_date

,cq4.answer                             AS CRM_comment
,su4.user_name                          AS CRM_name
,cq4.execution_date                     AS CRM_date

,cq5.answer                             AS HCR_comment
,cq5Bis.answer                          AS HCR_Comment2
,su5.user_name                          AS HCR_name
,cq5.execution_date                     AS HCR_date

,cq6.answer                             AS CRO_comment
,cq6Bis.answer                          AS CRO_comment2
,su6.user_name                          AS CRO_name
,cq6.execution_date                     AS CRO_date

,cq7.answer                             AS GM_comment
,cq7Bis.answer                          AS GM_comment2
,su7.user_name                          AS GM_name
,cq7.execution_date                     AS GM_date

from collect_question cq

left join collect_question cq1 on (cq.item_id=cq1.item_id and cq1.collect_question=@UHB_CQ 
                                    and cq1.step_name=@UHB_StepName  
                                    )

left join collect_question cq2 on (cq.item_id=cq2.item_id and cq2.collect_question=@HB_CQ 
                                    and cq2.step_name=@HB_StepName  
                                     )                                   

left join collect_question cq3 on (cq.item_id=cq3.item_id and cq3.collect_question=@UHCR_CQ 
                                    and cq3.step_name in (@UHCR_StepName,@UHCR_StepName1)  
                                     )  

left join collect_question cq4 on (cq.item_id=cq4.item_id and cq4.collect_question=@CRM_CQ 
                                    and cq4.step_name=@CRM_StepName  
                                     )  

left join collect_question cq5 on (cq.item_id=cq5.item_id and cq5.collect_question=@HCR_CQ 
                                    and cq5.step_name=@HCR_StepName)
left join collect_question cq5Bis on (cq.item_id=cq5Bis.item_id and cq5Bis.collect_question=@HCR_CQ2 
                                    and cq5Bis.step_name=@HCR_StepName)

left join collect_question cq6 on (cq.item_id=cq6.item_id and cq6.collect_question=@CRO_CQ 
                                    and cq6.step_name=@CRO_StepName)
left join collect_question cq6Bis on (cq.item_id=cq6Bis.item_id and cq6Bis.collect_question=@CRO_CQ2 
                                    and cq6Bis.step_name=@CRO_StepName)

left join collect_question cq7 on (cq.item_id=cq7.item_id and cq7.collect_question=@GM_CQ 
                                    and cq7.step_name=@GM_StepName)
left join collect_question cq7Bis on (cq.item_id=cq7Bis.item_id and cq7Bis.collect_question=@GM_CQ2 
                                    and cq7Bis.step_name=@GM_StepName)                                       


left join software_user su on cq.executed_by=su.user_id
left join software_user su1 on cq1.executed_by=su1.user_id
left join software_user su2 on cq2.executed_by=su2.user_id
left join software_user su3 on cq3.executed_by=su3.user_id
left join software_user su4 on cq4.executed_by=su4.user_id
left join software_user su5 on cq5.executed_by=su5.user_id
left join software_user su6 on cq6.executed_by=su6.user_id
left join software_user su7 on cq7.executed_by=su7.user_id

 where cq.collect_question=@RM_CQ
 and cq.step_name=@RM_StepName 

 and cq.item_id=172325

 Order By     cq.sequence_id desc
             ,cq1.sequence_id desc
             ,cq2.sequence_id desc
             ,cq3.sequence_id desc
             ,cq4.sequence_id desc
             ,cq5.sequence_id desc
             ,cq6.sequence_id desc
             ,cq7.sequence_id desc

【问题讨论】:

  • 你能发布 DDL 吗?索引是显而易见的答案。
  • 您的查询看起来很糟糕。我想表重新设计是解决方案。

标签: sql-server


【解决方案1】:

我真的很想知道如果你在 CTE SELECT 语句下面运行会有什么表现

select top 1 *
from (
select top 1   
 cq.answer                              AS RM_comment
,su.user_name                           AS RM_name
,cq.execution_date                      AS RM_date

,cq1.answer                             AS UHB_comment
,su1.user_name                          AS UHB_name
,cq1.execution_date                     AS UHB_date

,cq2.answer                             AS HB_comment
,su2.user_name                          AS HB_name
,cq2.execution_date                     AS HB_date

,cq3.answer                             AS UHCR_comment
,su3.user_name                          AS UHCR_name
,cq3.execution_date                     AS UHCR_date

,cq4.answer                             AS CRM_comment
,su4.user_name                          AS CRM_name
,cq4.execution_date                     AS CRM_date

,cq5.answer                             AS HCR_comment
,cq5Bis.answer                          AS HCR_Comment2
,su5.user_name                          AS HCR_name
,cq5.execution_date                     AS HCR_date

,cq6.answer                             AS CRO_comment
,cq6Bis.answer                          AS CRO_comment2
,su6.user_name                          AS CRO_name
,cq6.execution_date                     AS CRO_date

,cq7.answer                             AS GM_comment
,cq7Bis.answer                          AS GM_comment2
,su7.user_name                          AS GM_name
,cq7.execution_date                     AS GM_date


,cq.sequence_id sequence_id0
,cq1.sequence_id sequence_id1
,cq2.sequence_id sequence_id2
,cq3.sequence_id sequence_id3
,cq4.sequence_id sequence_id4
,cq5.sequence_id sequence_id5
,cq6.sequence_id sequence_id6
,cq7.sequence_id sequence_id7
from collect_question cq

left join collect_question cq1 on (cq.item_id=cq1.item_id and cq1.collect_question=@UHB_CQ 
                                    and cq1.step_name=@UHB_StepName  
                                    )

left join collect_question cq2 on (cq.item_id=cq2.item_id and cq2.collect_question=@HB_CQ 
                                    and cq2.step_name=@HB_StepName  
                                     )                                   

left join collect_question cq3 on (cq.item_id=cq3.item_id and cq3.collect_question=@UHCR_CQ 
                                    and cq3.step_name in (@UHCR_StepName,@UHCR_StepName1)  
                                     )  

left join collect_question cq4 on (cq.item_id=cq4.item_id and cq4.collect_question=@CRM_CQ 
                                    and cq4.step_name=@CRM_StepName  
                                     )  

left join collect_question cq5 on (cq.item_id=cq5.item_id and cq5.collect_question=@HCR_CQ 
                                    and cq5.step_name=@HCR_StepName)
left join collect_question cq5Bis on (cq.item_id=cq5Bis.item_id and cq5Bis.collect_question=@HCR_CQ2 
                                    and cq5Bis.step_name=@HCR_StepName)

left join collect_question cq6 on (cq.item_id=cq6.item_id and cq6.collect_question=@CRO_CQ 
                                    and cq6.step_name=@CRO_StepName)
left join collect_question cq6Bis on (cq.item_id=cq6Bis.item_id and cq6Bis.collect_question=@CRO_CQ2 
                                    and cq6Bis.step_name=@CRO_StepName)

left join collect_question cq7 on (cq.item_id=cq7.item_id and cq7.collect_question=@GM_CQ 
                                    and cq7.step_name=@GM_StepName)
left join collect_question cq7Bis on (cq.item_id=cq7Bis.item_id and cq7Bis.collect_question=@GM_CQ2 
                                    and cq7Bis.step_name=@GM_StepName)                                       


left join software_user su on cq.executed_by=su.user_id
left join software_user su1 on cq1.executed_by=su1.user_id
left join software_user su2 on cq2.executed_by=su2.user_id
left join software_user su3 on cq3.executed_by=su3.user_id
left join software_user su4 on cq4.executed_by=su4.user_id
left join software_user su5 on cq5.executed_by=su5.user_id
left join software_user su6 on cq6.executed_by=su6.user_id
left join software_user su7 on cq7.executed_by=su7.user_id

 where cq.collect_question=@RM_CQ
 and cq.step_name=@RM_StepName 

 and cq.item_id=172325
 ) t
 Order By
sequence_id0 desc
,sequence_id1 desc
,sequence_id2 desc
,sequence_id3 desc
,sequence_id4 desc
,sequence_id5 desc
,sequence_id6 desc
,sequence_id7 desc

【讨论】:

  • “CTE SELECT”如何?另外,这是怎么回答的?
  • 很快,但是 ORDER BY 是干什么用的(因为内部 SELECT 只返回一条记录)?
  • 首先应用排序。然后返回排序列表的第一行
【解决方案2】:

您只是选择了 TOP 1,因此假设 cq.sequence_id 是唯一的,则无需进一步排序:

  SELECT TOP 1 
  ...
  ORDER BY cq.sequence_id DESC

【讨论】:

  • 我需要这 2 个参数才能获得一条记录。最新的。
猜你喜欢
  • 2011-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-03
  • 1970-01-01
  • 2010-10-24
  • 2012-08-23
相关资源
最近更新 更多