2

我使用 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”根据@date 日期的输入年龄返回是/否。

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

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

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

任何帮助是极大的赞赏!谢谢!

4

1 回答 1

0

是的,如果查询不太复杂,查询优化器应该“看穿”视图进入其组成的 UNION-ed SELECT 语句,分别评估它们,并将结果连接起来。如果 Table1 上有索引,应该可以使用。我使用我们拥有的表格和您提出的相同功能概念对此进行了测试。我查看了原始 SELECT 到 Table1 的查询计划和 SELECT 到带有 UNION 的内联表值函数的查询计划,与 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

于 2014-03-06T19:46:13.163 回答