我有一个非常简单的LINQ查询:
List<table> list = ( from t in ctx.table
where
t.test == someString
&& t.date >= dateStartInt
&& t.date <= dateEndInt
select t ).ToList<table>();
获取查询的表大约有3000万行,但列test
和date
已编入索引。
当它应该返回大约5000行时,需要几分钟才能完成。
我还检查了LINQ生成的SQL命令。 如果我在SQL Server上运行该命令,则需要2秒钟才能完成。
LINQ的问题是什么? 这只是一个非常简单的查询,没有任何连接。
这是SQL Profiler显示的查询:
exec sp_executesql N'SELECT [t0].[test]
FROM [dbo].[table] AS [t0]
WHERE ([t0].[test] IN (@p0)) AND ([t0].[date] >= @p1)
AND ([t0].[date] <= @p2)',
N'@p0 nvarchar(12),@p1 int,@p2 int',@p0=N'123test',@p1=110801,@p2=110804
修改
真的很奇怪。测试时我注意到它现在快得多。 LINQ查询现在需要3秒才能完成大约20000行,这很不错。
更令人困惑的是: 这与我们的生产服务器上的行为相同。一个小时前它真的很慢,现在又快了。当我在开发服务器上进行测试时,我没有在生产服务器上进行任何更改。我唯一能想到的问题是两个服务器都是虚拟化的,并与许多其他服务器共享SAN。
我怎样才能知道这是不是问题?
答案 0 :(得分:2)
在责备LINQ之前,先找出发生实际延迟的地方。
然后开始责怪LINQ;)
答案 1 :(得分:2)
如果我必须猜测,我会说“参数嗅探”很可能,即它已经构建并缓存了基于一个参数集的查询计划,其中对于您当前的参数值非常不理想。您可以在常规TSQL中使用OPTION (OPTIMIZE FOR UNKNOWN)
解决此问题,但没有LINQ-to-SQL / EF方法来解释此问题。
我的计划是:
例如,使用LINQ-to-SQL,ctx.ExecuteQuery<YourType>(tsql, arg0, ...)
可用于在服务器上抛出原始TSQL(参数为{0}
等,如string.Format
)。就我个人而言,我倾向于“精致” - 非常相似的用法,但更快的物化器(但它不支持EntityRef<>
等延迟加载值 - 这通常是一件坏事,因为它导致N + 1)。
即。 (用短小精悍)
List<table> list = ctx.Query<table>(@"
select * from table
where test == @someString
and date >= @dateStartInt
and date <= @dateEndInt
OPTION (OPTIMIZE FOR UNKNOWN)",
new {someString, dateStartInt, dateEndInt}).ToList();
或(LINQ-to-SQL):
List<table> list = ctx.ExecuteQuery<table>(@"
select * from table
where test == {0}
and date >= {1}
and date <= {2}
OPTION (OPTIMIZE FOR UNKNOWN)",
someString, dateStartInt, dateEndInt).ToList();