相关疑难解决方法(0)

选择索引视图的聚集索引的因素有哪些?

简而言之,
哪些因素会影响查询优化器对索引视图索引的选择?

对我来说,索引视图似乎违背了我对优化器如何选择索引的理解。我之前看过这个问题,但 OP 并没有得到很好的接受。 我真的在寻找 guideposts,但我会编造一个伪示例,然后发布带有大量 DDL、输出、示例的真实示例。

假设我使用的是 Enterprise 2008+,理解 with(noexpand)

伪示例

以这个伪示例为例:我创建了一个包含 22 个连接、17 个过滤器和一个跨越 1000 万行表的马戏团小马的视图。这种观点实现起来很昂贵(是的,大写 E)。我将对视图进行 SCHEMABIND 和索引。然后一个 SELECT a,b FROM AnIndexedView WHERE theClusterKeyField < 84. 在我不知道的优化器逻辑中,执行了底层连接。

结果:

  • 无提示:4825 次读取 720 行,47 个 cpu 超过 76 毫秒,估计子树成本为 0.30523。
  • 使用提示:17 次读取,720 行,4 毫秒内 15 个 cpu,估计子树成本为 0.007253

那么这里发生了什么?我已经在Enterprise 2008、2008-R2 和 2012 中尝试过。根据我能想到的每个指标,使用视图索引的效率要高得多。我没有参数嗅探问题或倾斜的数据,因为这是临时的。

一个真实(长)的例子

除非你是一个受虐狂,否则你可能不需要或不想阅读这部分。

是的
,企业

Microsoft SQL Server 2012 - 11.0.2100.60 (X64) 2012 年 2 月 10 日 19:39:15 …

sql-server clustered-index materialized-view index-tuning

19
推荐指数
1
解决办法
2506
查看次数

尽管持久计算列与持久计算列定义中的 UDF 性能受到影响,但隐式转换警告

我需要一个计算列来解决隐式转换问题。我有一个声明为 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 版本的转换表,而不是使用计算列,但这似乎是很多不必要的开销。

sql-server functions warning computed-column

5
推荐指数
2
解决办法
889
查看次数

where 子句中的 dateadd - 在这种特定情况下如何避免完全扫描?

我有以下查询:

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

5
推荐指数
1
解决办法
1251
查看次数