6

現在、Entity Framework クエリのパフォーマンスを最適化しようとしています。特に、CPU 使用率を削減する方法を探しています。

dotTrace を使用して、さまざまなクエリを実行するときに最も CPU 時間がかかるものを分析しました。以下のスナップショットを参照してください。 dotTrace コール ツリー

このスナップショットはかなり単純なクエリからのものですが、最も時間のかかる操作である GetExecutionPlan() を示しています。これをさらに掘り下げると、式ツリー内のすべてのノードに対して再帰的に呼び出されるメソッド ComputeHashValue() に多くの時間が費やされていることがわかります。

このブログ投稿では、

Entity Framework は式ツリー内のノードをたどり、クエリ キャッシュに配置するために使用されるキーとなるハッシュを作成します。

そのため、ハッシュ値はクエリ キャッシュのキーとしてのみ使用されているようです。クエリで IEnumerable.Contains() を使用しているため、EF はそれらをキャッシュしません (この MSDN の記事 (3.2 章と 4.1 章) を参照してください)。したがって、次のようにクエリ プランのキャッシュを無効にしました。

var objectContext = ((IObjectContextAdapter)dbContext).ObjectContext;
var objectSet = objectContext.CreateObjectSet<Customer>();
objectSet.EnablePlanCaching = false;
// use objectSet for queries..

その後、ComputeHashValue() が呼び出されなくなることを願っていました。ただし、dotTrace によって表示されるコール ツリーに変化はなく、パフォーマンスはクエリ プラン キャッシュを有効にした場合と同じでした。

クエリ プランのキャッシュが無効になっているときに ComputeHashValue() がまだ必要な理由はありますか?

より複雑なクエリの場合、ComputeHashValue() へのすべての呼び出しは、クエリの実行に必要な CPU 時間全体の最大 70% を占めるため、これらの呼び出しを (必要がない場合) 回避すると、パフォーマンスに大きな影響を与えます。

4

1 に答える 1

0

残念ながら、それは Entity Framework が実装された方法ではありません。ソースコードを少し調べましたが、とにかく実行計画をコンパイルしているため、HashValue も計算していると理解しています。これは、EnablePlanCachingが有効で、キャッシュされたクエリが見つからない場合、この ComputedValue に基づいてキャッシュ マネージャーに追加できるためです。

このロジックを処理するクラスへのリンクは次のとおりです: EntitySqlQueryState

于 2014-05-03T19:35:21.640 に答える