SQLServerデータベースからのデータレコードのページリストを表示するMVCWebサイトがあります。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
このコードを実行すると、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]
電子メールフィルター句を削除すると、コントローラーのStopWatchはSQL Management Studioクエリと同様の応答時間を1秒未満で返します。したがって、SQL配管への基本的なインターフェイスは正しく機能しており、問題はLinq式の評価。また、これはサブスクライバーテーブルに100万行以上ある非常に大規模なデータベースであることにも言及する必要があります。
なぜこのような高い(x10)パフォーマンスの差があるべきなのか、そしてこれに対処するために何かできることがあれば、誰かに光を当てることができますか?