我有一个针对相当大的表运行的查询,我需要对其进行计数。
如果我使用文字,查询会在几秒钟内运行,但是当我将值作为变量放入时(我需要这样做),查询将永远持续下去,并且可能会进行全表扫描。
我已经阅读了大量有关此内容的文章,并且我理解它最有可能与参数嗅探有关,我不能假装我理解它,我只是想知道如何修复它,否则,我将不得不依靠生成的查询字符串在 C# 中调用它。
此查询将在几秒钟内运行..
SELECT Count(Id) FROM dbo.BeaconScan WHERE State = 'Archived' AND LastSeen < '29 February 2020';
这需要永远
DECLARE @Date DATE = '31 March 2020'
DECLARE @Status NVARCHAR(256) = 'Archived'
SELECT Count(Id) FROM dbo.BeaconScan WHERE State = @Status AND LastSeen < @Date;
最佳答案
SQL Server 根据行计数估计和启发式优化查询。这些估计可能因文字、局部变量或参数而异。
使用文字或参数(在应用程序代码中声明并随命令传递的参数),SQL Server 根据提供的实际值和统计直方图(如果列上存在索引或统计信息)估计计数。当统计数据是最新的时,这通常会产生准确的估计和最佳计划。
使用局部变量(T-SQL DECLARE
语句)或 OPTIMIZE FOR UNKNOWN
查询提示,SQL Server 根据值的总体平均密度估计计数并忽略实际值和直方图。这通常会产生一个折衷计划,该计划总体上可能足够好,但对于某些值可能不是最佳的。向具有局部变量的查询添加OPTION (RECOMPILE)
查询提示将使用实际的局部变量值进行优化,并产生与指定文字相同的计划。
请注意,没有 RECOMPILE
提示的参数化查询计划将被缓存和重用。重用计划时将忽略当前参数值,因此重用的查询计划对于当前参数值可能不是最佳的。这是OPTION (RECOMPILE)
可能提高性能的另一种情况。
考虑查询执行频率,明智地使用OPTION (RECOMPILE)
提示。编译开销可能超过频繁执行的查询(例如每秒多次)节省的运行时时间。
关于sql-server - 使用参数时查询很慢,但使用文字时查询很快,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64712644/