次の方法で共有


パフォーマンスの概要

データベースのパフォーマンスは、データベース、ネットワーク、データベース ドライバー、EF Core などのデータ アクセス 層など、コンポーネントのスタック全体にまたがる、膨大で複雑なトピックです。 EF Core などの高度なレイヤーや O/RM は、アプリケーション開発を大幅に簡素化し、保守容易性を向上させますが、非透過的な場合があり、実行中の SQL などのパフォーマンスクリティカルな内部の詳細が非表示になる場合があります。 このセクションでは、EF Core で優れたパフォーマンスを実現する方法と、アプリケーションのパフォーマンスを低下させる一般的な落とし穴を回避する方法の概要について説明します。

ボトルネックを特定し、測定、測定、測定する

パフォーマンスと同様に、問題を示すデータなしで最適化に突入しないことが重要です。偉大なドナルド・クヌスがかつて言ったように、「早期最適化はすべての悪の根源である」。 パフォーマンス診断セクションでは、アプリケーションがデータベース ロジックに時間を費やしている場所と、特定の問題のある領域を特定する方法を理解するさまざまな方法について説明します。 低速クエリが特定されると、解決策を検討できます。データベースにインデックスがありませんか? 他のクエリ パターンを試す必要がありますか?

常に自分のコードと考えられる代替手段をベンチマークします。パフォーマンス診断セクションには BenchmarkDotNet を使用したサンプル ベンチマークが含まれています。このベンチマークは、独自のベンチマークのテンプレートとして使用できます。 一般的なパブリック ベンチマークが特定のユース ケースに as-is 適用されることを想定しないでください。データベースの待機時間、クエリの複雑さ、テーブル内の実際のデータ量など、さまざまな要因が、どのソリューションが最適であるかに大きな影響を与える可能性があります。 たとえば、多くのパブリック ベンチマークは、データベースの待機時間がほぼゼロの理想的なネットワーク条件で実行され、データベース側で処理 (またはディスク I/O) をほとんど必要としない非常に軽いクエリを使用します。 これらは異なるデータ アクセス層の実行時オーバーヘッドを比較する場合に価値がある一方で、実際のアプリケーションでは通常、明らかにされる違いはごくわずかであり、データベースが実際の作業を実行し、データベースに対する待機時間が大きなパフォーマンス要因になります。

データ アクセスパフォーマンスの側面

全体的なデータ アクセスのパフォーマンスは、次の広範なカテゴリに分類できます。

  • 純粋なデータベース パフォーマンス。 リレーショナル データベースを使用すると、EF はアプリケーションの LINQ クエリを、データベースによって実行される SQL ステートメントに変換します。これらの SQL ステートメント自体は、多かれ少なかれ効率的に実行できます。 適切な場所の適切なインデックスは、SQL のパフォーマンスに大きな違いを生み出す可能性があります。また、LINQ クエリを書き換えることで、EF で SQL クエリが向上する可能性があります。
  • ネットワーク データ転送。 ネットワーク システムと同様に、ネットワーク上を行き来するデータの量を制限することが重要です。 ここでは、実際に必要になるデータのみを送信して読み込むだけでなく、関連エンティティを読み込むときにいわゆる "デカルト爆発" 効果を回避する方法についても説明します。
  • ネットワークラウンドトリップ。 データの行き来する量を超えて、ネットワークのラウンドトリップ時間は重要です。なぜなら、クエリがデータベースで実行される時間が、アプリケーションとデータベースの間でパケットが往復する時間に比べて小さいからです。 ラウンドトリップのオーバーヘッドは、環境によって大きく異なります。データベース サーバーが離れる距離が長いほど、待機時間が長く、各ラウンドトリップのコストが高くなります。 クラウドが登場すると、アプリケーションはますますデータベースから離れ、過剰なラウンドトリップを実行する "おしゃべり" アプリケーションではパフォーマンスが低下します。 そのため、アプリケーションがデータベースに接続するタイミング、実行されるラウンドトリップの数、その数を最小限に抑えることができるかどうかを正確に理解することが重要です。
  • EF ランタイムのオーバーヘッド。 最後に、EF 自体はデータベース操作にランタイム オーバーヘッドを追加します。EF は LINQ to SQL からクエリをコンパイルする必要があります (通常は 1 回だけ実行する必要があります)。変更の追跡によってオーバーヘッドが増加します (ただし、無効にすることができます)。実際には、データベースのクエリ実行時間とネットワーク待機時間が合計時間を占めるので、ほとんどの場合、実際のアプリケーションの EF オーバーヘッドは無視できる可能性があります。ただし、オプションの内容と、いくつかの落とし穴を回避する方法を理解することが重要です。

内部で何が起こっているかを知る

EF を使用すると、開発者は SQL を生成し、結果を具体化し、他のタスクを実行することで、ビジネス ロジックに集中できます。 他のレイヤーや抽象化と同様に、実際に実行されている SQL クエリなど、内部的に何が起こっているのかを隠す傾向もあります。 パフォーマンスは、必ずしもすべてのアプリケーションの重要な側面であるとは限りませんが、それが存在するアプリケーションでは、EF が実行していることを開発者が理解することが重要です。送信 SQL クエリを検査し、ラウンドトリップに従って N+1 の問題が発生していないことを確認します。

データベースの外部にキャッシュする

最後に、データベースとやり取りする最も効率的な方法は、データベースとまったくやり取りしを行わない方法です。 言い換えると、データベース アクセスがアプリケーションのパフォーマンスのボトルネックとして表示される場合は、要求を最小限に抑えるために、特定の結果をデータベースの外部にキャッシュする価値がある可能性があります。 キャッシュは複雑さを増しますが、特にスケーラブルなアプリケーションの重要な部分です。アプリケーション層は、負荷の増加に対応するためにサーバーを追加することで簡単にスケーリングできますが、通常、データベース層のスケーリングははるかに複雑になります。