在表值函数中混合索引和计算字段

时间:2013-10-27 17:28:51

标签: sql-server sql-server-2008 view indexing calculated-columns

我使用的是SQL Server 2008,但如果它很重要,可以使用更高版本。

我有2张表,其中有一些人的数据非常相似,但格式不同(这两组人之间没有交叉点)。

Table 1:    
int personID    
bit IsOldPerson  //this field is indexed

Table 2:
int PersonID
int Age

我想要一个具有与表1相同结构的组合视图。所以我编写了以下脚本(简化版):

CREATE FUNCTION CombinedView(@date date)
RETURNS TABLE
AS
RETURN        
    select personID as PID, IsOldPerson as IOP
    from Table1

    union all

    select personID as PID, dbo.CheckIfOld(Age,@date) as IOP
    from Table2
GO

函数“CheckIfOld”返回yes / no,具体取决于@date日期的输入年龄。

所以我在这里有两个问题:

一个。如果我尝试select * from CombinedView(TODAY) where IOP=true,SQL Server是否会单独执行以下操作:1)对于表1,使用字段IsOldPerson的索引并执行“聪明的”基于索引的结果选择; 2)对于表2,计算所有行的CheckIfOld并在计算过程中逐行拾取或拒绝行?

B中。如何检查这个特定情况下的执行计划,以了解我对问题(A)的猜测是否正确?

非常感谢任何帮助!谢谢!

1 个答案:

答案 0 :(得分:0)

是的,如果查询不是太复杂,查询优化器应该将视图“透视”到其组成的UNION-ed SELECT语句中,单独评估它们并连接结果。如果Table1上有索引,它应该能够使用它。我使用我们拥有的表和您提供的相同功能概念对此进行了测试。我查看了原始SELECT到Table1的查询计划和使用UNION的内联表值函数的SELECT,以及与Table1相关的查询计划部分是相同的 - 它使用了索引。

现在如果考虑到表现,我建议你做两件事之一:

  1. 如果(a)Table2读取繁重而不是重写,(b)您有空格,(c)您可以将CheckIfOld写为单个CASE语句(作为其名称和上下文)问题暗示),那么你应该考虑使用IsOldPerson的计算并在其中应用索引来创建Table2中的持久计算字段。

  2. 如果Table2写入较多,或者您没有其他字段的空间,则至少应考虑将CheckIfOld转换为内联函数。根据使用方式的不同,您可能会获得性能提升。在你的情况下,它会像这样使用:

    选择personID作为PID,IOP.IsOldPerson来自Table2 CROSS APPLY dbo.CheckIfOld(Age,@ date)AS IOP