交叉应用风格与性能

时间:2012-07-10 18:14:19

标签: sql-server cross-apply

我应该为每个别名表达使用单独的CROSS APPLY,还是在可能的情况下在同一个CROSS APPLY中定义多个表达式?

我正在重构许多非常复杂的SQL查询(通常有四到五页,有十几个JOIN),这些查询是在代码中生成的。它们通常嵌套五到六个深度查询,因为某些部分在不同情况下重复使用。嵌套查询的典型原因是一个查询提取一些值,执行计算,并为该值分配别名。然后封闭查询使用别名值等进行进一步计算。这是必要的,因为别名表达式只能在外部查询中引用,而不能在定义它的查询中的其他地方引用。 (替代方法,也存在于代码中,是在整个查询中重复相同的冗长子表达式。)

为了简化这个spaghetti-SQL,我开始使用CROSS APPLY折叠这些伸缩查询。通过使用CROSS APPLY,我可以分配别名并在同一查询中的其他地方使用它。请注意,我的CROSS APPLY子句都没有通过子选择引入新表,或者调用UDF。

首先,我在同一个CROSS APPLY中放了很多表达式。但是,我的代码需要模块化。在不同情况下将需要不同的字段,因为用户可以为过滤器选择字段,并且我们为不同的列生成类似的统计信息,因此创建许多相似的查询,这些查询彼此之间只有很小的差异。由于某些字段构建在其他字段上,并且某些字段依赖于先前在查询中定义的某些JOIN,因此我无法将所有字段放在同一个CROSS APPLY中。因此,交叉申请的数量可能会有所不同。

此外,从中提取的一些字段被新别名遮蔽并重新定义(通常用于删除NULL,提供默认值等)。因此,当CROSS APPLY定义字段在别处引用时,CROSS APPLY的表别名将需要被指定去除歧义。

这样做的结果是,我需要一种合理的方式来命名我的CROSS APPLY,我关心性能。如果CROSS APPLYs的数量发生变化,那么如果CROSS APPLYs用一个简单的计数器(例如computed1,computed2等)进行编号,那么给定的字段可能会看到它的名称引用从computed3变化。[FIELD NAME]到computed4。[FIELD] NAME]在查询的其余部分中具有连锁反应,这可能是通过调用不同的C#过程来组合的。这是一个维护问题。

我正在考虑的替代方案是将每个计算表达式放在一个单独的CROSS APPLY中,并且CROSS APPLY的名称将从表达式的别名派生。例如:

使用一个交叉申请:

CROSS APPLY (
    SELECT
          [TIV_BLDG] = (CASE [COVERAGE] WHEN 'TIV_BLDG' THEN VALUEAMT ELSE 0 END)

        , [TIV_OSTR] = (CASE [COVERAGE] WHEN 'TIV_OSTR' THEN VALUEAMT ELSE 0 END)

        , [TIV_CONT] = (CASE [COVERAGE] WHEN 'TIV_CONT' THEN VALUEAMT ELSE 0 END)

        , [TIV_TIME] = (CASE [COVERAGE] WHEN 'TIV_TIME' THEN VALUEAMT ELSE 0 END)

) computed2

使用四个CROSS APPLY:

CROSS APPLY (SELECT [TIV_BLDG] = (CASE [COVERAGE] WHEN 'TIV_BLDG' THEN VALUEAMT ELSE 0 END)) AS [TIV_BLDG_COMP]

CROSS APPLY (SELECT [TIV_OSTR] = (CASE [COVERAGE] WHEN 'TIV_OSTR' THEN VALUEAMT ELSE 0 END)) AS [TIV_OSTR_COMP]

CROSS APPLY (SELECT [TIV_CONT] = (CASE [COVERAGE] WHEN 'TIV_CONT' THEN VALUEAMT ELSE 0 END)) AS [TIV_CONT_COMP]

CROSS APPLY (SELECT [TIV_TIME] = (CASE [COVERAGE] WHEN 'TIV_TIME' THEN VALUEAMT ELSE 0 END)) AS [TIV_TIME_COMP]

如果我使用这种多重交叉应用方法,我可以轻松生成如果我添加新应用或删除它们不会改变的名称,并且我可以在代码中预测引用表别名的字段。但是,这意味着更多的CROSS APPLY语句。性能影响是什么?有没有更好的方法,使用CROSS APPLY或其他一些SQL Server功能? (我不需要将其作为跨数据库,因此仅限Microsoft的功能。)

1 个答案:

答案 0 :(得分:0)

如果存在性能劣势,则必须处于查询执行的编译阶段。随着执行计划被缓存,第二次执行查询时不会有性能损失。

SQL Server可以查看CROSS APPLY并将它们转换为简单的堆叠“计算标量”。

另一个潜在的问题可能是查询的大小。不确定AST节点或连接的数量是否存在任何相关限制(我认为CROSS APPLY在内部限制时计为连接)。

除了这些问题,我认为CROSS APPLYs是一个非常好的快速解决方案。