2010-11-19 10 views
2

ストアドプロシージャを使用するVS2008からORMとしてEntity Framework 4を使用してVS2010にプロジェクトを移行しました。LINQ to EntitiesはLINQ to SQL生成SQLと比較してSQL非効率的なSQLを生成しましたか?

私はデータベースからデータを取り出すために、かなり複雑なLINQクエリを実行しなければなりませんでした。私は通常最初にLINQPad(素晴らしいツールbtw!)を使ってLINQクエリを見つけようとします。

LINQ to Entities SQLが生成されたのは恐ろしい LINQ to SQLと比較して、これまでのストアドプロシージャと同様のSQL文が生成されていました。 L2Eクエリには非常に多くのネストされたSELECTとINNER JOINSがあって、それを見るだけで頭が痛いです!

これは私にとって不思議で、もう少し複雑なLINQクエリを選び、LINQとLINQをSQLに生成されたSQLに生成されたSQLと比較しました。結果は似ていましたが、L2E SQLは恐ろしく、非常に非効率でした(私はそれをベンチマークしませんでしたが、私にはSQL文を見れば分かります)

私は申し訳ありません現時点ではいくつかのサンプルクエリがありますが、興味があればダミーのデータベースを設定し、使用するものと似たクエリを作成できます(クエリとテーブルを難読化するとクエリが判読不能になり、無意味になります)

Entity Frameworkの経験ですか?誰もがひどいSQL文に気付かなかったのですか、ほとんどの人が気にしないだけでしたか?私が知るべきL2Eについて何か根本的なものが欠けていますか?

LINQ to SQLよりもEntity Frameworkを選択したことは非常に残念です。

編集:

だから私はいくつかのベンチマークを行なったし、WOW、私は驚きました!生成されたSQL文をSQL Server Management Studioのクエリウィンドウに配置し、各クエリを複数回実行しました。 WHILEループ1,10,100回でクエリを実行した平均結果を以下に示します。

1 time: 
    LINQ to SQL: 440ms 
    LINQ to Entities: 240ms 

10 times: 
    LINQ to SQL: 2900ms 
    LINQ to Entities: 910ms 

100 times: 
    LINQ to SQL: 31600ms 
    LINQ to Entities: 7000ms 

私は本当に驚いています!

私の次のテストでは、SQL文を生成して実行する簡単なC#プログラムを作成しました。私は便宜のためにLINQpadを使用しました。各テストでは、LINQ to SQLとLINQ to EntitiesデータプロバイダーをLINQPadで使用しました。クエリはまったく同じです。 は、テストプログラムは次のようになります。

void Main() 
{ 
    var sw = new Stopwatch(); 

    for(int i = 0; i < 5; i++) 
    { 
     sw.Start(); 
     for(int y = 0; y < 10; y++) 
     { 
      ExecuteQuery(); 
     } 
     sw.Stop(); 
     Console.WriteLine(string.Format("Pass {0}: {1}", i, sw.ElapsedMilliseconds)); 
     sw.Reset(); 
    } 
} 
private void ExecuteQuery() 
{ 
    //here is my 'complex' linq query 
    var dummy = (from p in....).ToList(); 
} 

私は少しがっかりしているこの時間は、次のように、結果は以下のとおりです。

 
LINQ to SQL: 
Run 0: 805 
Run 1: 726 
Run 2: 722 
Run 3: 717 
Run 4: 767 

LINQ to Entities: 
Run 0: 3031 
Run 1: 3231 
Run 2: 3085 
Run 3: 3127 
Run 4: 3148 

私は差がSQL文の生成によるものであると仮定しますか?あるいは私は完全に間違ってベンチマークですか?提案?

EDIT2: 私は(プロジェクトはASP.NET MVC 3 RCのWebアプリであることを言及するのを忘れてしまった)私たちのプロジェクトでLINQクエリを実装しています。基本的にカスタムメイドのグリッドを持つページを表示しています。エンティティへのLINQでグリッドのデータを読み込むには約300〜400ミリ秒かかります! LINQ to SQLを使用してデータをロードすると、約70〜80msかかります。これは、実際には上記のLINQPadのテストアプリでの私の結果と非常によく似ています。

私は過去数時間EFのパフォーマンスに関する問題を探していましたが、最初のクエリで多くの問題が見つかりました。実際、最初のクエリは遅くなりますが、約200msしかないため、最初のクエリは約600msかかりますが、それ以降のクエリは300〜400msかかります。私もprecompiling views with EdmGenについて読んだけど、違いはありませんでした。私は別のblog post that compared LINQ to SQL performance with EFを見つけましたが、これはEF 3.5のものでしたが、結果は似ているようです。それから私はblog post about EF with heavy inheritanceを見つけましたが、これは私の場合には当てはまりません。

"最初のクエリが遅い"タイプの投稿以外にも、私の問題に関連するものは何も見つかりませんでした。つまり、LinqとSQLの比較ではパフォーマンスは問題ありませんが、70msと300msの違いは大きな違いです!それは私たちのWebアプリケーションのユーザーエクスペリエンスに影響します。

最後に、クエリをプリコンパイルすることを試みます。パフォーマンスが改善されない場合、私はLINQ to SQLに確実に切り替えることになります(生成されたSQL自体は確かに高速です)。

+0

解決策が抽象的になればなるほど、SQLを生成するのが難しくなります。それでも、SQLパーサーが最適化していることがわかります。 – Lazarus

+0

問題は、まったく同じLINQクエリを実行し、LINQとLINQとLINQPadのLINQ to SQLプロバイダ間で実行し、生成されたSQLを比較したことです。または、私はあなたのコメントを理解していないかもしれません:) – Simon

+0

最初の例(whileループ)の結果が間違っていますか?その例から、LINQ to Entitiesは高速であるように見えますが、残りの部分がサポートしているとは思われません。 –

答えて

2

パフォーマンスのベンチマークを実際にしなかった。

SQLが悪く見えるだけで、それはひどく(常に)実行されているわけではありません。

Entity FrameworkまたはLINQ to SQLを使用する場合、アプリケーションがまだ自分の標準に準拠している限り、生成されたステートメントがどのようなものかは気にしません。パフォーマンスが許容レベルを下回った場合にのみ、クエリを微調整してより良いSQLを得ることができます。

+0

有効なポイント、私はいくつかのベンチマークを行い、報告します。私の前提は、L2Eクエリが3倍長くなり、SELECT文が3回以上ネストされているために遅くなるため、ここでSQLサーバ自体がいくつかの最適化を行っていますか?誰が知っている、私は行くし、ベンチマークします。 – Simon