我查询了表单
SELECT DISTINCT Str,Score
FROM Tab
WHERE Str in ('Str1', 'Str2', 'Str3') AND Type = 0
表架构
Str - varchar(8000)
Score - int
Type - bit
我还有Str
的索引,其中包含Type
和Score
IN
中的字符串数量变化
当我从C#构建直接查询时,它几乎是瞬间的
当我使用参数化查询(使用此处https://stackoverflow.com/a/337792/508593的方法)时,它变得非常慢 - 原始查询只需不到一秒钟。这是超时
查看SQL事件探查器和SSMS,这种缓慢似乎是由于语句被exec sp_executesql
包裹而导致索引扫描而不是搜索。直接查询使用提到的索引。使用sp_executesql
时,索引不会
我的怀疑是否正确,有没有办法解决这个问题?
除了Martin指定的根本原因外,解决方案是使用
显式设置参数类型 command.Parameters[i].DbType = DbType.AnsiString;
强制varchar而不是nvarchar
答案 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列表中强> 的