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

Rom*_*kij 3 sql-server query-optimization common-table-expression sql-server-2012

这是带有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  
Run Code Online (Sandbox Code Playgroud)

执行计划.请注意,CTE显示两次: 在此输入图像描述

问题:

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

Mar*_*ith 5

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

是否有可能通知QO重用CTE?

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

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

原则上是的.有关示例,请参阅Microsoft Research Paper 高效利用类似Subexpressions进行查询处理.

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

最可靠的方法是使用临时(非时间)表.请参阅提供一个提示以强制CTE或派生表的中间实现,以获得更多hacky变通方法.