【问题标题】:Linq to Sql and T-SQL Performance DiscrepancyLinq to Sql 和 T-SQL 性能差异
【发布时间】:2012-08-09 03:21:25
【问题描述】:

我有一个 MVC 网站,它提供来自 SQL Server 数据库的数据记录的分页列表。 UI 允许用户根据许多不同的标准过滤返回的数据,例如电子邮件地址。这是一段sn-p代码:

Stopwatch stopwatch = new Stopwatch();

var temp = SubscriberDB
   .GetSubscribers(model.Filter, model.PagingInfo);

// Inspect SQL expression here

stopwatch.Start();
model.Subscribers = temp.ToList();
stopwatch.Stop();     // 9 seconds plus compared to < 1 second in Query Analyzer

运行此代码时,秒表显示的执行时间约为 9 秒。如果我捕获生成的 SQL 表达式(就在使用 .ToList() 方法对其进行评估之前)并将其作为查询剪切到 SQL Server Management Studio 中,则执行时间会降至不到 1 秒。这里是生成的 SQL 表达式供参考:

SELECT [t2].[SubscriberId], [t2].[Email], [t3].[Reference] AS [DataSet], [t4].[Reference] AS [DataSource], [t2].[Created]
FROM (
    SELECT [t1].[SubscriberId], [t1].[SubscriberDataSetId], [t1].[SubscriberDataSourceId], [t1].[Email], [t1].[Created], [t1].[ROW_NUMBER]
    FROM (
        SELECT ROW_NUMBER() OVER (ORDER BY [t0].[Email], [t0].[SubscriberDataSetId]) AS [ROW_NUMBER], [t0].[SubscriberId], [t0].[SubscriberDataSetId], [t0].[SubscriberDataSourceId], [t0].[Email], [t0].[Created]
        FROM [dbo].[inbox_Subscriber] AS [t0]
        WHERE [t0].[Email] LIKE '%_EMAIL_ADDRESS_%'
        ) AS [t1]
    WHERE [t1].[ROW_NUMBER] BETWEEN 0 + 1 AND 0 + 20
    ) AS [t2]
INNER JOIN [dbo].[inbox_SubscriberDataSet] AS [t3] ON [t3].[SubscriberDataSetId] = [t2].[SubscriberDataSetId]
INNER JOIN [dbo].[inbox_SubscriberDataSource] AS [t4] ON [t4].[SubscriberDataSourceId] = [t2].[SubscriberDataSourceId]
ORDER BY [t2].[ROW_NUMBER]

如果我删除电子邮件过滤器子句,那么控制器的 StopWatch 会返回与 SQL Management Studio 查询类似的响应时间,不到 1 秒 - 所以我假设 SQL 管道的基本接口工作正常并且问题在于对 Linq 表达式的评估。我还应该提到,这是一个相当大的数据库,订阅者表中有超过 100 万行。

谁能解释一下为什么会有如此高 (x10) 的性能差异以及有什么办法可以解决这个问题?

【问题讨论】:

  • 造成这种情况的常见原因是:参数嗅探和不同的 SET 选项(ansi_nulls,...)。尝试搜索它们。
  • 如果您正在运行 SQL Server 的非 Express 版本,请启动 SQL Profiler 并查看这是否是唯一正在处理的查询。它还可能让您更深入地了解时间花在哪里。
  • @Neilski - 你能展示你的 GetSubscribers 方法吗?
  • 很难显示 GetSubscribers 的所有代码,因为它非常冗长。它实际上做了什么,它基于过滤器模型中设置的参数构建了一个表达式树。不屑一顾,我不确定它是否相关,因为 a) 最终结果是上面显示的 SQL 表达式,b) 其他过滤条件的性能符合预期,即相当快。
  • 我尝试在 Linq Profiler 下运行该应用程序 - 它没有显示任何意外,即 SQL 表达式与上面显示的相同。

标签: asp.net-mvc performance linq-to-sql


【解决方案1】:

嗯,不确定。完整的 1M 行可能需要安静的时间。电子邮件是否已编入索引?您可以使用 Email% 而不是 %Email% 运行查询,看看会发生什么?

【讨论】:

  • 问题不在于缺少索引之类的东西。问题是相同查询的持续时间差异。它应该总是很慢或总是很快。
  • 我尝试更改查询以运行 Email% 和 Web UI 的性能,并降低到与 SQL Server Management Studio 大致相同。从逻辑上我可以看到这种查询格式可以使用电子邮件索引,而 %Email% 不能,但它并不能解释为什么 SQL Server Management Studio 中的性能要好得多 - 出乎意料的是,正如您所期望的那样必须运行完整的记录扫描。
  • 偶尔一次(比如一年一次)我有同样的问题,Management Studio 中的查询比代码中使用的查询要快得多。也许 Management Studio 以某种方式对其进行了优化(这只是一个猜测)。
  • 谢谢 gsharp,您的评论中提到的链接 sommarskog.se/query-plan-mysteries.html 我认为这对解释问题有很长的路要走,所以我用“答案”标记了您的回复。我将研究如何在我的应用程序环境中协调查询。再次感谢。
猜你喜欢
  • 2010-11-30
  • 2011-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多