新しいプロジェクトのためにいくつかの .NET データベース アクセス テクノロジを評価したところ、Entity Framework を使用してリモート データベースにクエリを実行すると、パフォーマンスが低下することがわかりました。Entity Framework は、LinqToSql または SqlClient よりも 10 倍遅くなりました。多分あなたは私がそれを説明したり修正したりするのを手伝ってくれるでしょうか?
テスト パラメータ:
データベース:
- SQL Server 2008 エンタープライズ
- 1000 レコードの 1 つのテーブル
テーブル構造:
[dbo].[Master]( [Id] [int] IDENTITY(1,1) NOT NULL, [Value_Bit] [bit] NOT NULL, [Value_Float] [float] NOT NULL, [Value_DateTime] [datetime2](7) NOT NULL, [Value_Uniqueidentifier] [uniqueidentifier] NOT NULL, [Value_NVarchar100] [nvarchar](100) NOT NULL, [Value_NVarchar1000] [nvarchar](1000) NOT NULL, [InsertDate] [datetime] NOT NULL, [UpdateDate] [datetime] NOT NULL, [Version] [timestamp] NOT NULL)
ベンチマーク アプリケーション:
- .NET Framework 4 および 4.5
- WinForms-Application としてホストされる
データベース アクセス技術:
- エンティティ フレームワーク 5.0 (RC) および 4.3.1
- LinqToSQL
- SqlClient
コンピュータ (クライアント/サーバー):
- 同様のハードウェアを備えた 3 台の異なるコンピューター
- A と B が同じサブネットにある (例: 192.168.1.1 と 192.168.1.2)
- C は A および B とは異なるサブネットにあります (例: 192.168.2.1)
select * from Master
クライアントまたはサーバーとして異なるコンピューター上で、各データベース アクセス テクノロジを使用して SQL クエリを直接実行しました。平均時間は 1000 回の反復の結果です。
テスト シナリオ 1:
- クライアント:あ
サーバー: A
Entity Framework: 平均時間: 17 ミリ秒
- LinqToSQL: 平均時間: 20 ミリ秒
- SqlClient: 平均時間: 15 ミリ秒
テスト シナリオ 2:
- クライアント:あ
サーバー: B
Entity Framework: 平均時間: 144 ミリ秒
- LinqToSQL: 平均時間: 141 ミリ秒
- SqlClient: 平均時間: 140 ミリ秒
テスト シナリオ 3:
- クライアント:あ
サーバー: C
Entity Framework: 平均時間: 2145 ミリ秒
- LinqToSQL: 平均時間: 151 ミリ秒
- SqlClient: 平均時間: 156 ミリ秒
テスト シナリオ 4:
- クライアント:B
サーバー: C
Entity Framework: 平均時間: 2060 ミリ秒
- LinqToSQL: 平均時間: 141 ミリ秒
- SqlClient: 平均時間: 178 ミリ秒
テスト シナリオ 3 と 4 の Entity Framework が LinqToSQL または SqlClient よりも 10 倍遅いのはなぜですか?
Entity Framework 4.3.1、5 (RC) および .NET Framework 4 および 4.5 でテストしましたが、毎回同じ結果でした。遅延読み込みと追跡を無効にし、コンパイル済みクエリとビューの事前生成を使用しましたが、違いはありませんでした。
実行された SQL クエリを SQL プロファイラで調査したところ、SQL Server で Entity Framework のクエリに既に 2 秒かかっていることがわかりました (テスト シナリオ 3)。コンピューター A の Management Studio からクエリを実行すると、100 ミリ秒しかかかりませんでした。
dotTrace (http://www.jetbrains.com) を使用してベンチマーク アプリケーションのプロファイルを作成したところ、ほとんどの実行時間がメソッドによって消費されていることがわかりましたToList
。コール スタックをさらに詳しく調べると、メソッドが表示System.Data.SqlClient.SqlDataReader.GetString(Int32)
され、最後SNINativeMethodWrapper.SNIReadSyncOverAsync(SafeHandle, IntPtr&, Int32)
に常に消費されます。LinqToSql も SqlClient を使用しており、コール スタックはほぼ同じですが、実行時間は 10 倍高速です。
ボンネットの下で何が起こっているのかわかりません。コンピューター名の解決に関係している可能性がありますが、IP アドレスとそのコンピューター名を介してコンピューター C に ping を実行できます。それを説明したり、実行を高速化する方法をアドバイスしたりできる人はいますか?
前もって感謝します
マティアス