我有一个LINQ查询,它有很多变量,生成的SQL看起来像:
exec sp_executesql N'SELECT col1, col2
FROM MyTable [t3]
WHERE
(([t3].[col1] = @p0) AND ([t3].[col2] = @p1))
OR (([t3].[col1] = @p2) AND ([t3].[col2] = @p3))
...
N'@p0 varchar(32),@p1 varchar(32),@p2 varchar(32),@p3 varchar(32),...
,@p0='0',@p1='1',@p2='2',@p3='3',...
只要没有太多变量,例如150或更少,这就可以正常工作。但是当变量太多时,查询会显着减慢。
如果我有相同的查询,除了没有变量,例如:
SELECT col1, col2
FROM MyTable [t3]
WHERE
(([t3].[col1] = '0') AND ([t3].[col2] = '1'))
OR (([t3].[col1] = '2') AND ([t3].[col2] = '3'))
...
然后查询工作正常,即使有很多OR条件。
虽然我认为这确实是一个问题,当变量太多时SQL Server表现不佳,我想知道我是否可以通过不生成的SQL包含对变量的引用来解决LINQ中的这个问题,而是使用字符串文字
我意识到我可以通过不使用LINQ来解决这个问题,而是自己构建SQL,但希望有一个LINQ解决方案。
此外,虽然这个问题是关于LINQ的,但如果有一个加速查询涉及SQL Server的解决方案,我也会对此感兴趣。我应该补充一点,我在SQL Server 2005中看到了这个问题。
感谢您的帮助, 埃里克
答案 0 :(得分:2)
问题非常广泛。 LINQ本身可能与您的查询性能无关。
如果查询中有很多OR
,那么这就是SQL查询优化器对使用哪个索引感到困惑的原因。
在我看来,您首先需要关注SQL查询优化,添加适当的索引。当SQL查询被优化时,您将不会遇到LINQ问题。
[编辑]
如果使用字符串文字,最终可能会导致性能下降,因为SQL查询优化器将无法重用查询计划。每个查询都会触发新的查询计划生成。
答案 1 :(得分:2)
我不相信。事实上,Linq的一个功能是它可以防止用户Sql Injection攻击。
如果将查询参数加载到表中,然后将查询作为对表的连接运行,则可能会有更好的性能。
答案 2 :(得分:0)
正如其他人所说,参数不是问题。无论查询是否参数化,where子句中的许多OR都会混淆SQL Server。
一种解决方法是将查询更改为UNION查询,每个OR使用一个UNION。
E.g:
select ... from MyTable as t0 where t0.col1 = 0 and t0.col2 = 1
union all
select ... from MyTable as t1 where t1.col1 = 2 and t0.col2 = 3
您可以使用LINQ .Union方法轻松构建类似于循环中的查询:
List<Tuple<int, int>> IDPairs = new List<Tuple<int, int>> { new Tuple<int, int>(0,1), new Tuple<int, int>(2,3) }
IQueryable<MyTable> query = null;
foreach (Tuple<int, int> IDs in IDPairs)
{
if (query == null)
{
query = dc.MyTable.Where(w => w.Col1 == IDs.Item1 && w.Col2 == IDs.Item2);
}
else
{
query = query.Union(dc.MyTable.Where(w => w.Col1 == IDs.Item1 && w.Col2 == IDs.Item2));
}
}
var result = query.ToList();