Ale*_*sko 3 performance sql-server stored-procedures sql-server-2017 parameter-sniffing
在这里,我面临着存储过程中的特定语句出现的性能问题,该存储过程有时有很多语句
SP 每秒执行一次,通常完成时间不到 50 毫秒,但在出现问题时(可能每月一次,或每周几次 - 随机)要长得多,直到重新编译
SP有2个输入参数
SP供不同的应用使用
每个语句通常在约 1 毫秒内完成,但在出现问题时需要更长的时间
我必须承认我对什么是参数嗅探以及如何修复它只有初学者的了解。
绝对应该在教育上投入更多的时间,但在我的国家发生的所有事情都很难做到,请不要对我太严格
最常出现问题的一种说法:
UPDATE MyTable SET tMax = 0
WHERE tMax = 1
and tID in (SELECT b8 FROM #e538)
Run Code Online (Sandbox Code Playgroud)
在出现问题时,此更新语句有大量 LCK_M_U 等待,并开始与从不同会话执行的完全相同的语句发生死锁
另外两个说法:
INSERT #e534 (b4, d4, s4, r4)
SELECT tID, tDate, tStatusID, ID
FROM MyTable
WHERE tStatusID = (SELECT min(tStatusID)
FROM MyTable as f, LMyTable
WHERE tID = MyTable.tID
and tType = 1
and ltID = tStatusID
and ltComplete = 1 AND tActive = 1)
and tID in (select b8 from #e538)
AND tActive = 1
Run Code Online (Sandbox Code Playgroud)
和
INSERT #e534 (b4, d4, s4, r4)
SELECT tID, tDate, tStatusID, ID
FROM MyTable
WHERE (tDate = (SELECT top 1 tDate
FROM MyTable as f
WHERE tID = MyTable.tID
and tType = 1
AND tActive = 1
order by tDate desc))
and tType = 1
AND tActive = 1
and tID in (select b8 from #e538)
Run Code Online (Sandbox Code Playgroud)
当比较“好”与“坏”计划时,执行计划肯定是非常不同的,我可以看到 fromCXPACKET
并CXCONSUMER
等待这些语句,而通常没有任何语句
不幸的是,我没有“坏”执行计划,因为监控工具说“没有为此查询采样查询计划”。
MyTable 有 225+ 百万行,tID 是聚集索引键(BIGINT,虽然不是唯一的)
这是我的问题:
存储过程有输入参数,是的,但是这些特定语句没有参数,它们使用临时表来代替
这个参数在我的场景中嗅探,还是其他什么?
显然,它在出现问题时对 MyTable 进行索引扫描,而不是像大多数情况那样在聚集索引 (tID) 上使用查找。为什么可以呢?
我应该采取哪些进一步措施来调查和解决此问题?我即将启用查询存储并从该 SP 实现对表的日志记录,但还有什么?以及在查询存储中查看什么?
#e538 中有多少条记录?引擎将其转换为一系列 OR 子句,我发现在几十个之后,这些子句并不是最优的。根据其他因素,如果您的一个查询在临时表中具有明显更多的条目,则可能会将计划转移到适合该场景的计划,但不适用于另一种场景。
您可以将查询更改为类似这样以获得更一致的性能。
UPDATE M
SET tMax = 0
FROM MyTable AS M
INNER JOIN #e538 AS E ON E.b8 = M.tID
Run Code Online (Sandbox Code Playgroud)
另一种选择(尽管我会看看上面的重写是否可以解决您的问题)是添加一个提示以防止并行性。只需在有问题的陈述后面添加最后一行即可。
UPDATE M
SET tMax = 0
FROM MyTable AS M
INNER JOIN #e538 AS E ON E.b8 = M.tID
OPTION (MAXDOP 1)
Run Code Online (Sandbox Code Playgroud)