过滤时Sql视图慢的可能原因

tes*_*est 1 sql-server-2008 sql-server

我在 Sql Server 2008 中有一个视图,当只执行一个:

SELECT * FROM [Table]
Run Code Online (Sandbox Code Playgroud)

将返回大约 40000 行乘 130 列。以下是 6 次运行时的客户端统计信息(平均大约 7 秒):

客户统计(未过滤)

让我们假设这些时间都很好,当应用过滤器时问题就出现了。以下是 6 次运行时的客户端统计信息(平均大约 6 秒):

客户端统计(过滤)

有一些事情令人讨厌/令人沮丧:

  1. 时差平均只有1300ms左右。
  2. 过滤后的版本中仅返回 16 行。
  3. 我正在过滤的列是一个 int 列,它具有适当的索引。
  4. 过滤后的 SQL 看起来像:

    SELECT * FROM [Table] Where [IntColumn] = 15 -- returns 16 rows
    
    Run Code Online (Sandbox Code Playgroud)

我来找你们是因为我不知道为什么过滤后的版本可能需要这么长时间。SQL 引擎从执行开始就找到这 16​​ 行,然后计算/查找 130 列的值应该非常简单。我的问题真的是:

  1. 什么会导致这种情况?
  2. 我应该寻找什么来尝试解决这个问题?

以下是匿名执行计划(.zip 中的 .sqlplan):

  1. 匿名 Sql 计划 (Zippyshare)
  2. 匿名 Sql 计划 (Dropbox)

Aar*_*and 5

根据是否存在过滤器,计划的一小部分似乎有所不同。我试图拼凑正在发生的事情,但这是一些严重的混淆,试图匹配一切。如果不知道 Table1.Index9 和 Table2.Index38 之类的定义,就很难获得有关这里最昂贵的运算符的具体帮助。

与此同时,我有一些通用的性能建议,除了降低视图的复杂性,并且可能考虑使用不输出130 列的更简单的视图(尽量不要用斗鸡眼看这个连接图):

在此处输入图片说明

(1) 确保您的统计信息在所有基础表上都是最新的。几乎每一个操作都显示出估计行数和实际行数之间的巨大差距,这可能有助于解释次优的优化器选择。

(2) 通过将以下列添加到以下索引(可能作为INCLUDE列)来摆脱两次查找:

Table1.Column8  => Index3
Table1.Column43 => Index1
Run Code Online (Sandbox Code Playgroud)

(3) 其中一些表达方式令人抓狂,例如

CASE WHEN (
 Database0.Schema0.Table3.Column42 IS NOT NULL OR
 Database0.Schema0.Table3.Column42 IS NULL
)
AND Column56 IS NOT NULL
AND Database0.Schema0.Table3.Column55 IS NULL
AND Database0.Schema0.Table3.Column43 IS NULL
THEN (1) ELSE (0) END
Run Code Online (Sandbox Code Playgroud)

严重地?仔细查看该条款(并且该视图似乎散布着许多这样的条款)。没有人可以故意这样做。那么到底是什么脑死代码生成器造成了这个烂摊子呢?