我有以下两种查询方法。方法 1 在 20 秒内起作用。方法 2 甚至在数小时后仍未完成。
方法一
SELECT *,
SUBSTRING(IDAndCode,CHARINDEX ('$', IDAndCode)+1, LEN(IDAndCode) - 2) AS ICDCode
From dbo.MyTable
WHERE F.Fact_Diagnosis_BK LIKE 'SKI-CE:'+'%'
GO
方法二
DECLARE @DelimitingCharacter CHAR(1)
SET @DelimitingCharacter = '$';
SELECT *,
SUBSTRING(IDAndCode,CHARINDEX (@DelimitingCharacter, IDAndCode)+1, LEN(IDAndCode) - 2) AS ICDCode
From dbo.MyTable
WHERE F.Fact_Diagnosis_BK LIKE 'SKI-CE:'+'%'
GO
注意:以上两个是简化查询。实际查询可以在下面的执行计划中看到。
执行计划
实际执行计划——方法 1 https://www.brentozar.com/pastetheplan/?id=rJlcWTk3m
预计计划 - 方法 2: https ://www.brentozar.com/pastetheplan/?id=SJddO3en7
注意:方法2的计划使用Nested Loop
join而不是Hash Match
join
问题
我知道这可以通过添加来解决OPTION (RECOMPILE)
。如果我理解正确的话,缓慢的发生是因为 SQL Server 正在创建一个计划来适应NULL
变量的可能性。
在我的例子中,变量将Non-Null
在执行查询之前(保证)
在 SQL Server 2016 中,在不使用 OPTION (RECOMPILE) 的情况下,有什么可能告诉 SQL 引擎变量将为非空值并仅针对这种情况准备计划?
这种慢叫参数嗅探吗?(这里没有参数,是单机查询中的局部变量)
注意:我正在尝试查看选项以在不使用 RECOMPILE 的情况下使查询运行得更快。
参考资料:
以下是可以解决此问题的三种方法。欢迎更多的方法。
解决方案 1
使用临时表代替变量(@DelimitingCharacter)。
--并加入
执行计划:https ://www.brentozar.com/pastetheplan/?id=rJpehe5hQ
方案二
执行计划:https ://www.brentozar.com/pastetheplan/?id=B1nKne9nX
解决方案 3
执行计划:https ://www.brentozar.com/pastetheplan/?id=BkRgalqnX
注意
not null
这里。填充创建索引后。在查询正确时,
不需要
order by
条款以上改变是必须的。
你应该尝试一次
EXEC sys.sp_executesql
。您也应该尝试
Row_Number
一次,这样您就不需要第二个 Select 语句,也不需要临时表。不使用 ”*”。
只需尝试
With (Nolock)
提示:如果它有帮助,那么我们将对此进行更多讨论。它并不总是被认为是最佳实践,但请尝试一次。