LINQ查询速度极慢 - 为什么?

时间:2011-08-04 11:45:59

标签: c# linq performance datacontext

我有一个非常简单的LINQ查询:

List<table> list = ( from t in ctx.table
                     where
                     t.test == someString
                     && t.date >= dateStartInt
                     && t.date <= dateEndInt
                     select t ).ToList<table>();

获取查询的表大约有3000万行,但列testdate已编入索引。 当它应该返回大约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。

我怎样才能知道这是不是问题?

2 个答案:

答案 0 :(得分:2)

在责备LINQ之前,先找出发生实际延迟的地方。

  • 发送查询
  • 执行查询
  • 收到结果
  • 将结果转换为本地类型
  • 在UI中绑定/显示结果
  • 与此过程相关的任何其他事件

然后开始责怪LINQ;)

答案 1 :(得分:2)

如果我必须猜测,我会说“参数嗅探”很可能,即它已经构建并缓存了基于一个参数集的查询计划,其中对于您当前的参数值非常不理想。您可以在常规TSQL中使用OPTION (OPTIMIZE FOR UNKNOWN)解决此问题,但没有LINQ-to-SQL / EF方法来解释此问题。

我的计划是:

  1. 使用分析来证明查询中的时间丢失(而不是实现等)
  2. 一旦确认,请考虑使用直接TSQL方法来调用
  3. 例如,使用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();