使用参数化查询时,SQL查询速度极慢

时间:2013-10-18 09:56:08

标签: c# sql sql-server

我查询了表单

SELECT DISTINCT Str,Score 
FROM Tab 
WHERE Str in ('Str1', 'Str2', 'Str3') AND Type = 0

表架构

  Str - varchar(8000)  
  Score - int  
  Type - bit  

我还有Str的索引,其中包含TypeScore

IN中的字符串数量变化

当我从C#构建直接查询时,它几乎是瞬间的

当我使用参数化查询(使用此处https://stackoverflow.com/a/337792/508593的方法)时,它变得非常慢 - 原始查询只需不到一秒钟。这是超时

查看SQL事件探查器和SSMS,这种缓慢似乎是由于语句被exec sp_executesql包裹而导致索引扫描而不是搜索。直接查询使用提到的索引。使用sp_executesql时,索引不会

我的怀疑是否正确,有没有办法解决这个问题?


除了Martin指定的根本原因外,解决方案是使用

显式设置参数类型

command.Parameters[i].DbType = DbType.AnsiString;

强制varchar而不是nvarchar

3 个答案:

答案 0 :(得分:3)

参数必须为varchar而不是nvarchar

否则查询将有效

WHERE IMPLICIT_CAST(Str AS NVARCHAR(4000)) in (@P1,@P2,@P3) AND Type = 0

这会伤害索引的使用。

答案 1 :(得分:1)

从你的问题中不清楚你采取了哪种参数化方法;你提到的问题显示了不同的方法。

如果您使用了表值参数解决方案,您可能会遇到SQL Server创建的缓存查询计划,而不知道TVP参数中的项目数。默认情况下,IIRC,它假设10'000项,这将解释索引扫描而不是搜索。

话虽如此,尝试在参数化查询的末尾添加OPTION (RECOMPILE)提示,这将使SQL Server能够使用(当时已知的)项目计数重新编译查询。

答案 2 :(得分:0)

问题不在于参数化查询。

根据MSDN指定IN子句中硬编码的值时,最好对#values有一个很好的估计:

在IN子句中包含极大数量的值(数千个)会消耗资源并返回错误8623或8632.要解决此问题,请将项目存储在表中的IN列表中