我有一个MVC网站,提供了来自SQL Server数据库的分页列表数据记录。 UI允许用户根据许多不同的标准过滤返回的数据,例如,电子邮件地址。以下是一段代码:Linq to Sql和T-SQL性能差异
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
当此代码运行时,StopWatch显示大约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]
如果我删除电子邮件过滤条款,则控制器的秒表返回一个类似的响应时间在SQL Management Studio中查询,小于1秒 - 所以我假设SQL管道的基本接口工作正常,问题在于对Linq表达式的评估。我还应该提到,这是一个相当大的数据库,在订户表中具有1M以上的行数。
任何人都可以点亮为什么应该有这样一个高(x10)的性能差异,以及如果有什么可以做到解决这个问题?
这样做的常见原因是:参数嗅探和不同的SET选项(ansi_nulls,...)。尝试搜索它们。 – usr 2012-08-08 19:21:12
如果您正在运行SQL Express的非快速版本,请启动SQL Profiler并查看是否唯一正在执行的查询。它也可能让你更深入地了解时间花在哪里。 – Richard 2012-08-08 19:24:20
@Neilski - 你能显示你的GetSubscribers方法吗? – 2012-08-08 19:28:27