为什么CTE计算在查询计划中重复,并且如何在不重复代码的情况下优化它? [英] Why CTE calculation is duplicated in query plan and how to optimize it without duplicating code?

查看:102
本文介绍了为什么CTE计算在查询计划中重复,并且如何在不重复代码的情况下优化它?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在此查询的查询计划中,grp_set的计算重复了4次(不同的排序每次花费23%,因此花费23 * 4 =所有资源的92%):

Calculation of grp_set is duplicated 4 times in query plan of this query (distinct sort takes 23% each time, so it takes 23 * 4 = 92% of all resources):

with
     grp_set as (select distinct old_num,old_tbl,old_db,old_val_num from err_calc)
    ,grp as (select id = row_number() over (order by old_num),* from grp_set)

    ,leaf as (select grp.id ,c.* ,sort = convert(varchar(max),old_col) + " - " + severity + " - " + err
        from grp
        join err_calc c on
                            c.old_num   = grp.old_num
                        and c.old_tbl       = grp.old_tbl
                        and c.old_db        = grp.old_db
                        and c.old_val_num   = grp.old_val_num
    )

    select old_num,old_tbl,old_db,old_val_num,conc.*
        from (select sep=",") sep
        cross join grp
        cross apply (select
             old_col    = stuff((select sep + old_col   from leaf where leaf.id = grp.id order by leaf.sort FOR XML PATH("")),1,len(sep),"")
            ,old_val    = stuff((select sep + old_val   from leaf where leaf.id = grp.id order by leaf.sort FOR XML PATH("")),1,len(sep),"")
            ,severity   = stuff((select sep + severity  from leaf where leaf.id = grp.id order by leaf.sort FOR XML PATH("")),1,len(sep),"")
            ,err        = stuff((select sep + err       from leaf where leaf.id = grp.id order by leaf.sort FOR XML PATH("")),1,len(sep),"")
        ) conc

表err_calc包含约35万条记录,并且按old_db,old_tbl,new_tbl,severity,err,old_col,new_col,old_val_num,old_val,old_num,new_num仅具有一个索引

Table err_calc contains about 350K records and it has only one index by old_db,old_tbl,new_tbl,severity,err,old_col,new_col,old_val_num,old_val,old_num,new_num.

此查询的目的是由于SQL中缺少串联聚合,因此每组连接4个字符串字段。

The purpose of this query is to concatenate 4 string fields per group due to lack of concatenation aggregate in SQL.

等效查询和期望查询(如果存在串联聚合或已使用CLR实现) d如果order by可以应用于聚合来源,并且所有分组字段都可以由 grouping引用。* 为:

Equivalent and desired query if concatenation aggregate existed or was implemented with CLR and if order by could be applied to source of aggregation and if all grouping fields could be referenced by grouping.* would be:

select grouping.*
    ,severity   =conc(sep+severity)
    ,err        =conc(sep+err)
    ,old_col    =conc(sep+old_col)
    ,old_val    =conc(sep+old_val)
    from err_calc
    cross join (select sep=',') sep
    group by old_num,old_tbl,old_db,old_val_num
    order by old_col,severity,err


推荐答案

因为它像子查询一样使用,并且多次使用。 cf. 在同一查询中多次调用CTE

Because it is used like a subquery, and used multiple times. cf. Calling CTE multiple times in same query

您应该使用CTE而不是 JOIN 代替 CROSS APPLY 来重写查询,然后将字符串串联逻辑放在查询的 SELECT 部分中,则CTE将被调用一次。

You should rewrite your query with a JOIN with your CTE instead of a CROSS APPLY, and put the logic of string concatenation in the SELECT part of your query, then the CTE will be called once.

这篇关于为什么CTE计算在查询计划中重复,并且如何在不重复代码的情况下优化它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆