LINQ查询非常慢-为什么

本文关键字:为什么 非常 查询 LINQ | 更新日期: 2023-09-27 18:04:42

我得到了一个非常简单的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查询大约20000行需要3秒,这是相当不错的。

更令人困惑的是:在我们的生产服务器上也是如此。一小时前它很慢,现在又快了。因为我是在开发服务器上进行测试的,所以我没有更改生产服务器上的任何内容。我能想到的唯一问题是这两个服务器都是虚拟化的,并且与许多其他服务器共享SAN。

我怎样才能知道问题出在哪里?

LINQ查询非常慢-为什么

在责备LINQ之前,首先找出实际的延迟发生在哪里。

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

然后开始责备LINQ;)

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

我的计划是:

  1. 使用分析来证明时间在查询中丢失了(与物化等相反)
  2. 一旦确认,考虑使用直接TSQL方法调用

例如,对于LINQ-to-SQL, ctx.ExecuteQuery<YourType>(tsql, arg0, ...)可用于向服务器抛出原始TSQL(参数为{0}等,如string.Format)。就我个人而言,我倾向于"dapper"-非常相似的用法,但更快的物化器(但它不支持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();