我有一个 MVC 网站,它提供了来自 SQL Server 数据库的数据记录的分页列表。UI 允许用户根据许多不同的标准过滤返回的数据,例如电子邮件地址。这是一段代码:
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 表达式的评估。我还应该提到,这是一个相当大的数据库,订阅者表中有超过 1M 行。
任何人都可以解释为什么会有如此高的(x10)性能差异以及什么,如果可以采取任何措施来解决这个问题?