[敬礼]
(检查一个)
[ ] Well trained professional, [ ] Casual reader, [ ] Hapless wanderer,
Run Code Online (Sandbox Code Playgroud)
我有一个(检查所有适用的)
[ ] query [ ] stored procedure [ ] database thing maybe
Run Code Online (Sandbox Code Playgroud)
运行良好(如果适用)
[ ] yesterday [ ] in recent memory [ ] at some point
Run Code Online (Sandbox Code Playgroud)
但现在突然变慢了。
我已经检查过以确保它没有被阻止,并且它不是某些长时间运行的维护任务、报告或其他带外进程的受害者。
有什么问题,我应该怎么做,我可以提供哪些信息来获得帮助?
[*Insert appropriate closing remarks*]
Run Code Online (Sandbox Code Playgroud) performance sql-server execution-plan parameter-sniffing query-performance
这不是关于:
这不是关于接受用户输入或使用变量的全面查询的问题。
这完全是关于ISNULL()在WHERE子句中使用where用NULL金丝雀值替换值以与谓词进行比较的查询,以及在 SQL Server中将这些查询重写为SARGable 的不同方法。
你为什么不在那边坐?
我们的示例查询针对 SQL Server 2016 上 Stack Overflow 数据库的本地副本,并查找NULL年龄或年龄 < 18 岁的用户。
SELECT COUNT(*)
FROM dbo.Users AS u
WHERE ISNULL(u.Age, 17) < 18;
Run Code Online (Sandbox Code Playgroud)
查询计划显示了一个非常周到的非聚集索引的扫描。
scan 操作符显示(由于 SQL Server 的最新版本中对实际执行计划 XML 的补充)我们读取了每一行。
总的来说,我们进行了 9157 次读取并使用了大约半秒的 CPU 时间:
Table 'Users'. Scan count 1, logical reads 9157, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, …Run Code Online (Sandbox Code Playgroud) 那里有很多跟踪标志。有些有据可查,有些没有,还有一些在 2016 版本中找到了默认行为状态的方法。除了官方支持渠道、微软员工等,还有什么方法可以找到新的跟踪标志?
我已经在这里和这里阅读了 Aaron Bertrand 最近的几篇文章,但没有发现任何关于新跟踪标志的信息。
我将 mssqlsystemresource 的数据和日志文件复制到一个新位置,并像常规数据库一样附加它以浏览系统表和视图,但没有立即发现任何内容。我考虑过列出已知跟踪标志的列表,并循环遍历不在该列表中的数字,以查看 DBCC TRACEON 允许哪些,但想先在这里提出问题。
假设启用它们的 DBCC 命令必须检查某些资源以确保跟踪标志有效,那么它会到达哪里?是否有包含列表的 .dll 或其他系统文件?
我知道这个问题撒了一个广泛的网络,但促使它阅读的原因是阅读了具有特定预期行为的 Trace Flag 以及 2016 年没有产生所描述效果的新功能。我最初的想法是,也许数字以某种方式转置了,比如 7129 变成了 7219。我希望得到一个范围内的有效跟踪标志列表,比如 7000-7999,以寻找排列。将它们全部作为 DBCC TRACEON 标志和启动参数进行测试,再加上针对功能行为测试结果,将会非常麻烦。
我们在虚拟 Windows 2008 R2 服务器上运行 SQL Server 2008 R2 (10.50.1600)。在将 CPU 从 1 核升级到 4 核并将 RAM 从 4 GB 升级到 10 GB 后,我们注意到性能更差。
我看到的一些观察:
有没有人遇到过这个问题?
根据 sp_BlitzErik,我跑了
EXEC dbo.sp_BlitzFirst @SinceStartup = 1;
Run Code Online (Sandbox Code Playgroud)
给我这些结果。
我有一个要优化的 SQL 查询:
DECLARE @Id UNIQUEIDENTIFIER = 'cec094e5-b312-4b13-997a-c91a8c662962'
SELECT
Id,
MIN(SomeTimestamp),
MAX(SomeInt)
FROM dbo.MyTable
WHERE Id = @Id
AND SomeBit = 1
GROUP BY Id
Run Code Online (Sandbox Code Playgroud)
MyTable 有两个索引:
CREATE NONCLUSTERED INDEX IX_MyTable_SomeTimestamp_Includes
ON dbo.MyTable (SomeTimestamp ASC)
INCLUDE(Id, SomeInt)
CREATE NONCLUSTERED INDEX IX_MyTable_Id_SomeBit_Includes
ON dbo.MyTable (Id, SomeBit)
INCLUDE (TotallyUnrelatedTimestamp)
Run Code Online (Sandbox Code Playgroud)
当我完全按照上面写的方式执行查询时,SQL Server 扫描第一个索引,导致 189,703 次逻辑读取和 2-3 秒的持续时间。
当我内联@Id变量并再次执行查询时,SQL Server 寻找第二个索引,导致只有 104 次逻辑读取和 0.001 秒的持续时间(基本上是即时的)。
我需要变量,但我希望 SQL 使用好的计划。作为临时解决方案,我在查询上放置了索引提示,查询基本上是即时的。但是,我尽量避免使用索引提示。我通常假设如果查询优化器无法完成它的工作,那么我可以做(或停止做)一些事情来帮助它,而无需明确告诉它该做什么。
那么,当我内联变量时,为什么 SQL Server 会提出更好的计划?
对我来说,我有一个关于 SARGability 的有趣问题。在这种情况下,它是关于对两个日期列之间的差异使用谓词。这是设置:
USE [tempdb]
SET NOCOUNT ON
IF OBJECT_ID('tempdb..#sargme') IS NOT NULL
BEGIN
DROP TABLE #sargme
END
SELECT TOP 1000
IDENTITY (BIGINT, 1,1) AS ID,
CAST(DATEADD(DAY, [m].[severity] * -1, GETDATE()) AS DATE) AS [DateCol1],
CAST(DATEADD(DAY, [m].[severity], GETDATE()) AS DATE) AS [DateCol2]
INTO #sargme
FROM sys.[messages] AS [m]
ALTER TABLE [#sargme] ADD CONSTRAINT [pk_whatever] PRIMARY KEY CLUSTERED ([ID])
CREATE NONCLUSTERED INDEX [ix_dates] ON [#sargme] ([DateCol1], [DateCol2])
Run Code Online (Sandbox Code Playgroud)
我会经常看到的是这样的:
/*definitely not sargable*/
SELECT
* ,
DATEDIFF(DAY, [s].[DateCol1], [s].[DateCol2])
FROM
[#sargme] AS [s] …Run Code Online (Sandbox Code Playgroud) 简而言之,
哪些因素会影响查询优化器对索引视图索引的选择?
对我来说,索引视图似乎违背了我对优化器如何选择索引的理解。我之前看过这个问题,但 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 …
设想:
我们有两个表Tbl1&Tbl2在订阅服务器上。在Tbl1正在从出版商复制的Server A,它有两个触发器-插入和更新。触发器将数据插入和更新到Tbl2.
现在,我们必须清除(大约 9 亿条记录),Tbl2其中总共有 1000+ 万条记录。下面是一个月到一分钟的数据分布。
我在找什么;
在没有任何生产问题、数据一致性和可能没有停机时间的情况下清除该数据的最快方法。所以,我想按照以下步骤操作,但卡住了:(
脚步:
一旦 BCP-in 完成,使用 tsql 脚本插入新的增量数据。
挑战是 -如何处理增量“更新”语句? …
虽然其高质量博客Posts®工作,我碰到了一些优化的行为,我发现真的真气有趣。我没有立即得到解释,至少不是我满意的解释,所以我把它放在这里,以防有人聪明出现。
如果您想继续学习,可以在此处获取Stack Overflow 数据转储的 2013 版本。我正在使用 Comments 表,上面有一个额外的索引。
CREATE INDEX [ix_ennui] ON [dbo].[Comments] ( [UserId], [Score] DESC );
Run Code Online (Sandbox Code Playgroud)
当我像这样查询表时,我得到了一个奇怪的查询计划。
WITH x
AS
(
SELECT TOP 101
c.UserId, c.Text, c.Score
FROM dbo.Comments AS c
ORDER BY c.Score DESC
)
SELECT *
FROM x
WHERE x.Score >= 500;
Run Code Online (Sandbox Code Playgroud)
Score 上的 SARGable 谓词不会被推入 CTE。它在计划后期的过滤器运算符中。
我觉得很奇怪,因为它ORDER BY与过滤器位于同一列。
如果我更改查询,它会被推送。
WITH x
AS
(
SELECT c.UserId, c.Text, c.Score
FROM dbo.Comments AS c
) …Run Code Online (Sandbox Code Playgroud) sql-server ×10
performance ×4
archive ×1
functions ×1
index ×1
index-tuning ×1
optimization ×1
parallelism ×1
trace-flags ×1
trigger ×1