1

linq to entityを使用しているWebサイトがありますが、最近非常に遅いことがわかりました。トラブルシューティングの結果、linq to entityを使用してデータベースからデータを検索すると、toList()関数などのCPU時間が非常に長くなることがわかりました。データベースに大量のデータがあり、応答が遅くなっている可能性があることはわかっていますが、この問題を引き起こす可能性のある他の理由があるのではないかと思います。

この種の問題を最適化するにはどうすればよいですか?考えられる理由は次のとおりです。

  1. ToList()すべてのオブジェクトの外部オブジェクト(外部キー)をロードする可能性がありますが、オブジェクトのみをロードするように強制するにはどうすればよいですか?

  2. 接続プールが小さすぎませんか?

他に考えられる理由があれば教えてください。この問題を解決するための正しい方向を教えてください。

4

2 に答える 2

5

Linqでは、クエリが列挙されると、クエリは一連の操作の結果をソースに返します。

IQueryable<Customer> myQuery = ...

foreach(Customer c in myQuery)  //enumerating the query causes it to be executed
{

}

List<Customer> customers = myQuery.ToList();
  // ToList will enumerate the query, and put the results in a list.
  // enumerating the query causes it to be executed.

クエリを実行するには、いくつかのことが必要です(順不同)

  • データベース接続はプールから引き出されます。
  • クエリはクエリプロバイダーによって解釈されます(この場合、プロバイダーはエンティティに対してlinqであり、解釈はSQLの形式です)
  • 解釈されたフォームはデータベースに送信され、データベースで実行され、データオブジェクトが返されます。
  • 着信データオブジェクトを目的のクエリ出力に変換するには、何らかのメソッドを生成する必要があります。
  • データベース接続がプールに返されます。
  • 目的のクエリ出力では、コードに返される前に状態追跡が行われる場合があります。

さらに、データベースにはいくつかのステップがあり、SQLサーバーへのクエリの観点からここにリストされています。

  • クエリテキストが受信され、既存のプランのクエリプランキャッシュと照合されます。
  • プランが存在しない場合は、新しいプランが作成され、クエリオプティマイザによってプランキャッシュに貼り付けられます。
  • クエリプランが実行されます-IO/ロック/CPU/メモリ-これらのいずれかがボトルネックである可能性があります
  • クエリ結果が返されます。特に結果セットが大きい場合、ネットワークがボトルネックになる可能性があります。

つまり、クエリの問題がどこにあるかを見つけるには、測定を開始する必要があります。これらのターゲットをチェックする順序で注文します。これは完全なリストではありません。

  1. クエリの翻訳されたSQLテキストを取得します。これにはSQLサーバープロファイラーを使用できます。デバッガーを使用できます。それについて行くには多くの方法があります。クエリテキストがオブジェクトに必要なものを返すことを確認してください。それ以上でもそれ以下でもありません。クエリされたテーブルが期待に一致することを確認してください。クエリを数回実行します。

  2. 結果セットを見てください。それは合理的ですか、それとも500ギガの結果を見ていますか?すべてが必要でなかったときに、テーブル全体が照会されましたか?デカルト結果が予期せず生成されましたか?

  3. クエリの実行プランを取得します(SQL Studioで、show estimated execution planボタンをクリックします)。クエリは、期待するインデックスを使用していますか?計画は奇妙に見えますか(おそらく悪い計画がキャッシュから来ました)?クエリは期待どおりの順序でテーブルに対して機能し、期待どおりにネスト/マージ/ハッシュ結合を実行しますか?クエリがそれに値しない場合、並列化が開始されますか(これは、インデックスの不良/ IOのTONSの兆候です)?

  4. クエリのIOを測定します。(SQLサーバーで、SET STATISTICS IO ONを発行します)。テーブルごとの論理IOを調べます。どのテーブルが目立ちますか?繰り返しになりますが、クエリをサポートできるテーブルアクセスまたはインデックスの順序が間違っているかどうかを確認してください。

    ここまで進んだら、問題を見つけて修正した可能性があります。あなたがしなかった場合に備えて、私は続けます。

  5. クエリの実行時間を列挙の実行時間と比較します。大きな違いがある場合は、データオブジェクトを解釈するコードが遅いか、生成が遅い可能性があります。また、クエリの翻訳に時間がかかった可能性もあります。これらは解決するのが難しい問題です(LinqToSqlでは、コンパイルされたクエリを使用してそれらを分類します)。

  6. コードが実行されているマシンのメモリとCPUを測定します。上限がある場合は、コードプロファイラーまたはメモリプロファイラーを使用して問題を特定して解決します。

  7. マシンのネットワーク統計を確認します。特に、TCPViewを使用してマシンのTCPソケット接続を確認することをお勧めします。ソケットリソースが悪用される可能性があります(1分間に数千を開閉するなど)。

  8. 他の接続によって保持されているロックがないかデータベースを調べます。

それで十分だと思います。確認すべき明らかなことを忘れなかったことを願っています。

于 2012-05-18T04:31:21.753 に答える
0

問題の解決策は、MSDNのパフォーマンスに関する考慮事項(エンティティフレームワーク)にあります。特に

正しい量のデータを返す

一部のシナリオでは、データベースへのラウンドトリップが少なくて済むため、Includeメソッドを使用してクエリパスを指定する方がはるかに高速です。ただし、他のシナリオでは、関連オブジェクトをロードするためのデータベースへの追加のラウンドトリップが高速になる場合があります。これは、結合が少ない単純なクエリではデータの冗長性が低くなるためです。このため、関連するオブジェクトを取得するさまざまな方法のパフォーマンスをテストすることをお勧めします。詳細については、関連オブジェクトのロードを参照してください。

1つのクエリで大量のデータが返されないようにするには、クエリの結果をより管理しやすいグループにページングすることを検討してください。詳細については、「方法:クエリ結果のページ」を参照してください。

于 2012-05-18T08:19:23.820 に答える