简而言之,
哪些因素会影响查询优化器对索引视图索引的选择?
对我来说,索引视图似乎违背了我对优化器如何选择索引的理解。我之前看过这个问题,但 OP 并没有得到很好的接受。 我真的在寻找 guideposts,但我会编造一个伪示例,然后发布带有大量 DDL、输出、示例的真实示例。
假设我使用的是 Enterprise 2008+,理解
with(noexpand)
以这个伪示例为例:我创建了一个包含 22 个连接、17 个过滤器和一个跨越 1000 万行表的马戏团小马的视图。这种观点实现起来很昂贵(是的,大写 E)。我将对视图进行 SCHEMABIND 和索引。然后一个 SELECT a,b FROM AnIndexedView WHERE theClusterKeyField < 84
. 在我不知道的优化器逻辑中,执行了底层连接。
结果:
那么这里发生了什么?我已经在Enterprise 2008、2008-R2 和 2012 中尝试过。根据我能想到的每个指标,使用视图索引的效率要高得多。我没有参数嗅探问题或倾斜的数据,因为这是临时的。
除非你是一个受虐狂,否则你可能不需要或不想阅读这部分。
是的
,企业版。
Microsoft SQL Server 2012 - 11.0.2100.60 (X64) 2012 年 2 月 10 日 19:39:15 …
我需要一个计算列来解决隐式转换问题。我有一个声明为 VARCHAR 的列,它应该只存储整数,但偶尔会被带有字符串的第三方应用程序错误填充,因此该列需要保持原样。
该表通常连接到一个将该值存储为 INT 的表。我定义了一个 PERSISTED 计算列,用于将该 VARCHAR 转换为 INT:
[iOrderNumber] AS (CONVERT([int],
case
when [ordernumber] like '#%' then (-99) when isnumeric([ordernumber])=(0) then (-99)
when CONVERT([bigint],[ordernumber],(0))>(2147483647) then (-99)
else [ordernumber]
end,(0))) PERSISTED NOT NULL
Run Code Online (Sandbox Code Playgroud)
使用计算列上的适当索引,现在可以连接到 INT 列的查询的性能显着提高。但是,即使在更新表而不是读取表时发生转换,执行计划仍会显示隐式转换警告。
我尝试在计算列定义中使用 UDF 来消除警告(我找到了一篇建议这样做的博客文章),但随后我的查询的执行时间更长,并且使用了更多的 CPU,尽管逻辑读取保持不变。但是 UDF 确实消除了警告。
除了错误之外,还有其他理由考虑警告吗?是否有理由将优化器对使用 UDF 定义的持久计算列的处理视为错误?
更重要的是,有没有办法摆脱警告,而不会招致 UDF 解决方案的性能损失?
我考虑使用触发器和包含数据的 VARCHAR 和 INT 版本的转换表,而不是使用计算列,但这似乎是很多不必要的开销。
我有以下查询:
SELECT u.userId,
app.applicationId
FROM app.application AS app
INNER JOIN app.applicant AS ap
ON ap.applicantId = app.applicantId
INNER JOIN usr.[user] AS u
ON u.userId = ap.userId
LEFT JOIN msg.emailTemplateSent AS t
ON t.toUserId = u.userId
AND t.emailTemplateName = 'v4_before_sixWeek_latestFlight_reminder'
WHERE Convert(Date, GETUTCDATE()) =
DATEADD(week,-6,Convert(Date, app.flightDateLatest ))
AND t.emailEventId IS NULL
ORDER BY app.applicationId ASC
Run Code Online (Sandbox Code Playgroud)
请再次注意where子句的第一行:
Convert(Date, GETUTCDATE()) = DATEADD(week,-6,Convert(Date, app.flightDateLatest ))
Run Code Online (Sandbox Code Playgroud)
我可以以可以使用我的索引的方式更改此设置吗?索引实际上被使用了,但它是一个完整的扫描。
也可以在这里看到:
这是我的索引定义:
USE [APCore];
CREATE NONCLUSTERED INDEX i_flightDateLatest
ON [app].[application] ( flightDateLatest ASC )
INCLUDE ( [applicantId] , …
Run Code Online (Sandbox Code Playgroud) index sql-server execution-plan sql-server-2016 query-performance