web-dev-qa-db-ja.com

エンティティフレームワークとストアドプロシージャ-パフォーマンス測定

Entity Frameworkがストアドプロシージャよりもどれだけ遅いかを確認しようとしています。開発を容易にするためにEntity Frameworkを使用できるように上司を説得したいと思っています。

問題は、パフォーマンステストを実行したところ、EFはStored Procsよりも約7倍遅いようです。これを信じるのは非常に難しいと思います。これは決定的なテストですか? EFテストのパフォーマンスを向上させるためにできることはありますか?

        var queries = 10000;

        //  Stored Proc Test
        Stopwatch spStopwatch = new Stopwatch();
        spStopwatch.Start();
        for (int i = 0; i < queries; i++ )
        {
            using (var sqlConn = new SlxDbConnection().Connection)
            {
                var cmd = new SqlCommand("uspSearchPerformanceTest", sqlConn) { CommandType = CommandType.StoredProcedure };

                cmd.Parameters.AddWithValue("@searchText", "gstrader");
                sqlConn.Open();
                SqlDataReader dr = cmd.ExecuteReader();

                List<User> users = new List<User>();
                while (dr.Read())
                {
                    users.Add(new User
                    {
                        IsAnonymous = Convert.ToBoolean(dr["IsAnonymous"]),
                        LastActivityDate = Convert.ToDateTime(dr["LastActivityDate"]),
                        LoweredUserName = dr["LoweredUserName"].ToString(),
                        MobileAlias = dr["MobileAlias"].ToString(),
                        UserId = new Guid(dr["UserId"].ToString()),
                        UserName = (dr["UserName"]).ToString()
                    });
                }

                var username = users.First().UserName;
                sqlConn.Close();
            }
        }
        spStopwatch.Stop();
        Console.WriteLine("SP - {0} Queries took {1}", queries, spStopwatch.ElapsedMilliseconds );

        //  EF  Test
        Stopwatch entityStopWatch = new Stopwatch();

        var context = new SlxDbContext();
        var userSet = context.Set<User>();
        entityStopWatch.Start();
        for (int i = 0; i < queries; i++)
        {
            User user = userSet.Where(x => x.UserName == "gstrader").First();
        }

        entityStopWatch.Stop();
        Console.WriteLine("Entity - {0} Queries took {1}", queries, entityStopWatch.ElapsedMilliseconds);

結果:

SP-10000件のクエリに2278件かかりました

エンティティ-10000クエリに16277かかりました

57
reach4thelasers

クエリを最適化するためにできることがいくつかあります。 MSDNで 素敵な概要を見つけることができます。

しかし、正直に言うと、手動マッピングを使用するストアドプロシージャのパフォーマンスは常に高速です。しかし、パフォーマンスはどれほど重要ですか?ほとんどのプロジェクトでは、開発時間はパフォーマンスよりもはるかに重要です。開発が困難だったのは何ですか?解析付きの生のクエリまたはEntity Frameworkクエリ?

ORMは、手書きのアプローチよりもはるかに優れたパフォーマンスを発揮するため、設計されていません。開発が非常に簡単なので、私たちはそれらを使用します!

Entity Frameworkを使用してアプリケーションを作成し、すべてのクエリをリポジトリパターンの背後に隠すと、本当に迅速に開発でき、パフォーマンスが問題になったら、アプリケーションを測定してボトルネックを検出できます。その後、クエリの一部は最適化が必要であり、ストアドプロシージャと手動マッピングに移動できます。

81
Wouter de Kort

@Wouter de Kortと同意します...さらに、手順に移動する必要がある場合は、EFを手順とともに使用して、一方から他方への移行を支援できます。

機能の統合を適切に設計された手順にすると、一般的なアプリケーションでは手順への移行が速くなります。つまり、できるだけ多くの作業をone sproc呼び出しで行います。たとえば、ショッピングカートMVCアプリでは、ユーザーがチェックアウトボタンをクリックすると、mightのようにORMを使用します。

  1. ユーザーの認証を検索します(ログインはまだ有効ですか?)
  2. 許可を調べます(彼らは上記のアイテムを購入できますか?、特別な要件はありますか?)
  3. 在庫数量を調べて、処理中に枯渇していないことを確認します
  4. 支払い前にアイテムを予約(利用可能な在庫から削除)するためにDBに書き込みます
  5. 支払い情報を調べる
  6. ロギング...?

または、完全に異なるステップである場合もありますが、いずれの場合でも、MVCアプリはORMを使用してDBを複数回呼び出し、次のステップに進みます。

このすべてのロジックが1つの適切に記述されたsprocにカプセル化されている場合、sprocの呼び出しは1回だけで完了です。 MVC-ORMルートでは、データをDBからドライバーにコピーし、ORM(通常はネット経由で別のホストに)に配信し、MVCアプリで読み取って簡単な決定を下し、すべての手順が完了するまで繰り返します。 。そのチェックアウト手順をカプセル化するsprocを使用する場合、実行するデータのコピーと移動、ネットワークIO、コンテキスト切り替えなどが大幅に少なくなります。

MVC-ORMソリューションをこのように考えてください。人「A」は事実のみを知っており、人「B」は、彼が提起しない特定の事実で意思決定を行うためのすべての知識を持っています。人「B」は事実について「A」にメールします。 「A」からの回答に基づいて、「B」は決定を下す前にさらにいくつかの事実を要求する場合があります。それは多くのやり取りのメッセージです。

すべての事実と意思決定を行う知識を持っている人が1人いる場合、1つの質問をするだけで、彼らの脳はすべてを内部的に処理して答えを出します。他の人との審議は含まれません。当然、より高速になります。

必ずしもbetterとは限りません。事実を決定から分離するということは、これらのコンポーネントを個別に交換/テストできることを意味します。ただし、MVCとDBを結婚している場合、それは「非問題」です。

一方、多くのMVCファンはSQLの作成を嫌い、自然災害としてSQLに決定ロジックを組み込むことを検討しています。そのような人々にとっては、MVCが使用するのと同じ言語で記述されたロジックを持つことが不可欠です。なぜなら、開発がスピードアップするからです。一部のRDMBSの場合、MVCが使用する言語と同じ言語でsprocを記述できるため(「Net:SQL ServerのsprocはC# .Net; Postgresql関数(sprocなし)はPerl、Pythonで記述できますPHP et。al)この場合の利点は、1回の呼び出しで複数のステップをカプセル化する高速sprocを使用できることです既にコーディングが迅速なプログラミング言語を使用できます。

10
MikeM

注意することが重要です

.NET Framework 4.5以降では、LINQクエリはcachedautomaticallyです。ただし、コンパイルされたLINQクエリを使用して、後の実行でこのコストを削減することができ、コンパイルされたクエリは、自動的にキャッシュされるLINQクエリよりも効率的です。

MSDN Compiled Queries(LINQ to Entities)

2
Daniel