执行计划的CTE表现。是显示两次,还是两次处理?

时间:2014-02-26 12:22:44

标签: sql-server sql-server-2012 query-optimization common-table-expression

这是带有CommonTableExpression的SQL。注意,USERS_PROJECTS_CTE使用了两次。

 WITH USERS_PROJECTS_CTE (PRO_ID, SHOW_IAS, USERNAME)
   AS
   (
      SELECT up.PRO_ID, up.SHOW_IAS, ISNULL(u.FIRST_NAME, '') + ' ' + ISNULL(u.SECOND_NAME, '')
      FROM SFMIS07_PRO.USERS_PROJECTS up
      INNER JOIN SFMIS07_ADM.USERS  AS u 
                ON  up.USER_ID = u.ID
      WHERE up.IS_RESP_PERSON = 1 AND up.valid_to is null
   )
   SELECT up.PRO_ID, 
          up1.USERNAME as RESP_USER1,
          up2.USERNAME as RESP_USER2,
          up.COUNT_
   FROM SFMIS07_PRO.PRO_RESP_USERS_KERNEL_MV  AS up 
        LEFT JOIN USERS_PROJECTS_CTE  AS up1 ON up.PRO_ID = up1.PRO_ID AND up1.SHOW_IAS=1  
        LEFT JOIN USERS_PROJECTS_CTE  AS up2 ON up.PRO_ID = up2.PRO_ID AND up2.SHOW_IAS=0  

执行计划。请注意,CTE显示两次: enter image description here

问题:

  1. 我是对的,CTE不仅要显示两次,而且要处理两次?
  2. 是否可以通知QO重用CTE?
  3. 原则上QO是否有可能检测到“相同的SQL片段”并重用结果(我想通过应对已经准备好的数据来实现这一点)?
  4. 如何优化查询(不使用时态表:)?

1 个答案:

答案 0 :(得分:5)

  

我是对的,CTE不仅要显示两次,而且要处理两次?

  

是否可以通知QO重复使用CTE?

不是直接但有一些黑客可以鼓励这一点。

  

原则上QO可能检测到“相同的SQL片段”   并重用结果(我想象通过应对来实现这一点   已准备好的数据)?

原则上是的。有关示例,请参阅Microsoft研究论文Efficient Exploitation of Similar Subexpressions for Query Processing

  

如何优化查询(不使用时态表:)?

最可靠的方法是使用临时(非暂时)表。有关更多hacky解决方法,请参阅Provide a hint to force intermediate materialization of CTEs or derived tables