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



我使用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)中的猜测是否正确?

任何帮助将不胜感激!谢谢!

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

现在,如果性能是一个问题,我建议您做以下两件事之一:

  1. 如果 (a) Table2 是读取密集型而不是写入密集型,(b) 您有空间,并且 (c) 您可以将 CheckIfOld 编写为单个 CASE 语句(正如问题中的名称和上下文所暗示的那样),那么您应该考虑使用 IsOldPerson 的计算在 Table2 中创建一个持久计算字段,并对其应用索引。

  2. 如果 Table2 写入量很大,或者您没有空间容纳其他字段,则至少应考虑将 CheckIfOld 转换为内联函数。您可能会获得性能提升,具体取决于它的使用方式。在您的情况下,它将像这样使用:

    选择人员 ID 作为 PID、IOP。表2中的IsOldPerson交叉应用dbo。CheckIfOld(Age,@date) AS IOP

最新更新