August 2010

Volume 25 Number 08

高速 SQL - 階層の相互作用のプロファイルによるデータベース呼び出しの調整

Mark Friedman | August 2010

多くのアプリケーションが、明示的に複数の層を使用するよう設計されています。複数の層を使用する場合は、データ アクセス層呼び出しのパフォーマンスが、アプリケーション全体の応答性にとって重要な要素になります。複数の層を使用すると、アプリケーションの柔軟性が高まります。n 層方式を採用すると、主要コンポーネントを明確に分離できます。そのため、信頼性とスケーラビリティが共に向上します。複数の層を使用するとスケーラビリティが高まるのは、コンポーネントが明確に異なる層に分離され、使用可能なコンピューティング リソースを容易に分散できるためです。

階層の相互作用のプロファイル (TIP) は、アプリケーションが依存するデータ層のパフォーマンスを把握するのに役立つよう設計されています。TIP は Visual Studio プロファイリング ツールの新機能で、ADO.NET 準拠データベースの同期呼び出しの完了を待機するときに、データ層での遅延時間と、.NET Framework アプリケーションの操作性を測定および報告します。データベースに頻繁に呼び出しを行い、応答時間が問題となるアプリケーションでは、TIP を利用することで、応答待ち時間に最も影響を与えるデータ要求を把握できます。

今回の記事では、この TIP を紹介し、TIP のレポート機能について例を挙げて説明します。また、TIP で使用されるインストルメンテーション テクノロジについても説明し、TIP を効果的に使用して、データベース処理に関連するパフォーマンス上の問題を診断する際のベスト プラクティスをいくつか紹介します。ここでは、データを集中的に扱い、LINQ to SQL テクノロジを使用して Microsoft SQL Server のデータにアクセスする、2 層形式のサンプル ASP.NET Web アプリケーションを利用して、TIP の使い方を調べます。そして最後に、データ層のパフォーマンスをさらに細かく把握するため、SQL 管理の標準パフォーマンス ツールを使用して、TIP パフォーマンス データを補強する方法について説明します。

TIP の概要

TIP は、プロファイルの実行中に、アプリケーションのデータ層の呼び出し時間を測定するインストルメンテーション コードを動的に追加します。Visual Studio プロファイリング ツールは、Visual Studio 2010 Premium Edition と Visual Studio 2010 Ultimate Edition に付属しています。

プロファイル セッションを開始するには、[分析] メニューの [パフォーマンス ウィザードの起動] をクリックするか、[デバッグ] メニューの [パフォーマンス分析の開始] をクリックするか、キーボード ショートカット (Alt キーを押しながら F2 キーを押します) を使用します。パフォーマンス ウィザードの最初のページでは、プロファイル方法を選択します。

TIP は、すべてのプロファイル方法 (サンプリング、インストルメンテーション、メモリ、または同時実行) と併用できますが、既定では有効になっていません。TIP を有効にするには、パフォーマンス ウィザードの 4 ページ目で、[ウィザードの完了後にプロファイルを起動する] チェック ボックスをオフにする必要があります (TIP がまだ有効になっていないため、アプリケーションを起動して、プロファイルを行う準備が整っていません)。特に、データ層の相互作用のデータに最も注目している場合は、最良の結果を得るために、まず、プロファイル方法としてサンプリングを選択することをお勧めします。その主な理由は、サンプリングが、アプリケーションのパフォーマンスに与える影響が最も少ないためです。

TIP によるデータ収集を有効にするには、パフォーマンス エクスプローラーで、パフォーマンス ウィザードによって作成されたばかりのパフォーマンス セッションを右クリックして [プロパティ] を表示します。[プロパティ] ダイアログ ボックスで、[階層の相互作用] タブをクリックし、[階層の相互作用のプロファイルを有効にする] チェック ボックスをオンにします。[OK] をクリックしてダイアログ ボックスを閉じます。これで TIP が有効になり、アプリケーションのプロファイルを開始する準備が整いました。

実際にプロファイルを実行するには、パフォーマンス エクスプローラーのツール バーにある [プロファイルの開始] をクリックします。

Visual Studio で TIP を有効にする完全な手順については、Habib Heydarian のブログの記事「Walkthrough: Using the Tier Interaction Profiler in Visual Studio Team System 2010」(チュートリアル: Visual Studio Team System 2010 で階層の相互作用のプロファイルを使用する、英語) を参照してください (https://blogs.msdn.com/b/habibh/archive/2009/06/30/walkthrough-using-the-tier-interaction-profiler-in-visual-studio-team-system-2010.aspx)。

TIP によるパフォーマンスの測定方法

TIP は、プロファイルの実行中にアプリケーションにコードを挿入し、このコードで、アプリケーションが使用する ADO.NET データ層への呼び出しを測定します。階層の相互作用のプロファイルをアクティブにすると、Visual Studio Profiler は、ソリューションの Microsoft intermediate language (MSIL) を検査して、ADO.NET 関数への参照を探します。Just-In-Time (JIT) コンパイラを呼び出して、アプリケーションが実行するネイティブ コードを生成する前に、Visual Studio Profiler は、ADO.NET の主要メソッドにインストルメンテーションを追加する命令を挿入します。追加されるインストルメンテーション コードが、各 ADO.NET 呼び出しにかかる時間を監視します。

アプリケーションを実行すると、TIP は計時データをキャプチャして報告します。アプリケーションのプロファイルが行われているときに、このインストルメンテーション コードが ADO.NET 呼び出しの時間を記録し、データベース呼び出しで使用されたコマンド テキストのコピーもキャプチャします。アプリケーションの実行中、SQL、OLE DB、Open Database Connectivity (ODBC)、SQL Server Compact (SQL CE) API など、ADO.NET クラスの同期メソッドを使用して実行される、すべてのデータベース アクセスに関する計時データが収集されます。また、アプリケーションで LINQ to SQL または Entity Framework API を使用して SQL データベースにアクセスする場合も、計時データをキャプチャします。

計時データは、プロファイル セッション中に収集された他のデータと一緒に、Visual Studio プロファイラー ファイル (.vsp) に格納されます。外部のデータベースに呼び出しを行うアプリケーションでは呼び出しをアウトプロセスで実行するため、TIP がアプリケーションをインストルメント化するために追加する命令が、アプリケーションのパフォーマンス全体に影響を与えることはほとんどありません。

パフォーマンスのチューニング

一般的な設計パターンでは、Web アプリケーションがプレゼンテーション層、ビジネス ロジック層、およびデータ層に分割されます。この設計パラダイムにより、アプリケーションがコンポーネント パーツに分割され、信頼性、拡張性、およびスケーラビリティを確保できるようになります。多層アプリケーションは、データ エンティティを、関連する一連のテーブル内の行および列として論理的に参照するビジネス ロジック コンポーネントを使用して、データ層にアクセスします。SQL Server などのデータベースが、データベース テーブルに関連付けられた物理データを管理する方法は、アプリケーションからは意識されないように設計されています。

信頼性とスケーラビリティを確保するため、大規模 Web アプリケーションでは、多くの場合、複数のコンピューターでプールを構成し、アプリケーションの各層に関連付けられた処理ロジックをこのプールで処理します。複数の層をサポートする複数のコンピューターでは、1 台のコンピューターを監視してもアプリケーションを完全には把握できないため、パフォーマンス分析に関して特殊な課題が生み出されます。

たとえば、SQL Server のようなデータベース システムを使用して、アプリケーションのデータ ストアへのアクセスを管理および仲介する場合、アプリケーション ロジックとは切り離してデータ層を作成します。SQL Server などのデータベースに格納されるアプリケーション データは、それぞれ独立したプロセス アドレス空間で、そのアドレス空間固有のデータ ストアを使って管理されます。アプリケーション データを含むデータベースは、アプリケーションと同じ物理コンピューター上に存在することもありますが、ネットワーク プロトコルを使用して、異なるコンピューターからアクセスされる可能性も高くなります。

アプリケーションから外部データベースに渡される SQL コマンドや、外部データベース上で操作する SQL コマンドは、アウトプロセス呼び出しになります。サンプリング プロファイルでは、このようなアウトプロセス呼び出しの完了を待機している間、アプリケーションが休止状態になっていることはわかりますが、アプリケーションが待機中になっている理由や、この遅延の時間はわかりません。インストルメンテーション プロファイルや同時実行プロファイルでは、この遅延時間を測定できますが、問題が発生している SQL コマンドや、完了に長い時間がかかる理由はわかりません。

外部データベースと通信する多層アプリケーションでは、多くの場合、主にデータベース コンポーネントが、アプリケーションの応答時間全体に影響を与えます。Visual Studio プロファイリング ツールには、サンプリング、インストルメンテーション、メモリ割り当て、同時実行など、ざまさまなプロファイル方法が用意されています。ただし、これらの方法は、外部データベースへアクセスする際に発生するパフォーマンスの問題を、TIP データを使用しないで識別する場合にはあまり役に立たない可能性があります。

TIP データを使用すると、データベース関連の遅延の詳細を確認したり、遅延が発生した理由を把握したりできます。また、データベース ベンダーが提供する他のパフォーマンス ツールと組み合わせて使用すると、データベースのパフォーマンスに大きく依存するアプリケーションのパフォーマンスを向上するために、実行可能な処理を知ることもできます。

TIP はアプリケーション コードにインストルメンテーションを追加するため、アクセスしているデータベース インスタンスを物理的に検索できる場合は、データベース コマンドに関連する計時データを収集できます。収集できる計時データは、たとえば、アプリケーションと同じコンピューター上に物理的に存在する SQL Server インスタンスのアウトプロセス呼び出しなどで、これは通常、単体テストのシナリオです。それぞれ独立した物理コンピューター上に存在する SQL Server インスタンスに対して、同じアプリケーションの統合テストや負荷テストを行う準備が整っているときは、TIP では、その構成の測定データを引き続き収集できます。実際に、TIP による測定データを利用して、このような 2 つの異なる構成のパフォーマンスを比較することができます。

TIP では、キャッシュ メモリの構成、物理データ記憶装置、データベースのパーティション分割、データベースのインデックス作成、データベース テーブルの設計など、外部データベースのパフォーマンスとチューニングに関して使用可能な数多くのオプションの影響を比較できます。また、仮想マシン上で SQL Server を実行した場合のパフォーマンスの影響を直接測定できます。

TIP レポートの基礎

TIP が有効な状態でプロファイル セッションが完了したら、アプリケーションの ADO.NET データ層との相互作用に関連がある計時データが、階層相互作用のビューにまとめて表示されます。図 1 に、収集された TIP データがアクティブで、プロファイルの実行中に ADO.NET の処理が行われる場合の、プロファイラーの例を示します。

Visual Studio Profiler による階層の相互作用のレポート

図 1 Visual Studio Profiler による階層の相互作用のレポート

レポートの上半分には、収集したプロファイル データの概要が示されます。ASP.NET アプリケーションの場合、ビューは URL 別に整理されます。レポートでは、Web アプリケーションの GET 要求に対するサーバー側の応答時間を、URL 別にグループ化します。

アプリケーション層の下には、データベース層 (この例では、AdventureWorks サンプル データベース) への各接続が示されます。また、ADO.NET を使用したデータベースの同期呼び出しに関連付けられた、サーバー側の ASP.NET 要求の処理時間の一部が測定され報告されます。この例では、3 つの集計行が表示され、各集計行には、プロファイル中の Web サイトに存在する 3 つの異なる ASP.NET ページに関するデータベース処理が一覧にまとめられています。プロファイル中に特定された ASP.NET ページごとに、プロファイルの実行中に処理された ASP.NET 要求の数と、生成された各応答メッセージに対するサーバー側の応答時間が報告されます。

他の集計行には、スタイルシート、Javascript コード、およびページにリンクされた画像に対する要求など、他の GET 要求の応答時間データが示されます。プロファイラーが特定の ASP.NET 要求と関連付けることができないデータベース呼び出しは、その他の要求のカテゴリにグループ化されます。

データ層を使用する Windows デスクトップ アプリケーションやコンソール アプリケーションをプロファイルするときは、レポートはプロセス名に基づいて、ADO.NET のアクティビティを整理します。

各 Web ページの集計行の下にはそれぞれ 1 行の集計行があり、ASP.NET 処理の間に行われたデータベースの同期要求の数がデータベース接続別に報告されます。この例では、CustomerQuery.aspx に対する 6 つの ASP.NET 要求が、1 つのデータベース接続経由で処理されたことがわかります。この 6 つの要求は、サーバーでの処理に合計で 0.959 秒かかり、平均の応答時間は 160 ミリ秒です。これらの要求により、12 件の SQL クエリが発行され、完了におよそ 45 ミリ秒かかっています。データベース要求を待機した時間は、この Web ページの応答メッセージの生成にかかった時間の約 5% にすぎません。

データベース接続の集計行を 1 つ選択すると、階層相互作用のビューの下半分に、アプリケーションが発行した具体的な SQL コマンドが表示されます。この SQL コマンドは、ページ グループ内で、発行されたコマンド テキスト別にグループ化され、経過時間に応じて並べ替えられます。

この例では、1 つ目の SQL コマンドは 3 回、2 つ目のコマンドは 6 回、そして 3 つ目のクエリは 3 回発行されています。集計レポートでは単一の行にまとめられている特定のクエリのそれぞれの経過時間が、詳細ビューでは個別に報告されます。経過時間の合計、コマンドのすべてのインスタンスの平均経過時間、およびクエリごとに観察された最短と最長の遅延を確認できます。

SQL コマンドの詳細行をダブルクリックすると、発行された SQL コマンドの全テキストが [Database Command Text] (データベース コマンド テキスト) ウィンドウに表示されます。これは、アプリケーションが実行中に、ADO.NET インターフェイスを通じて、データベースに実際に渡したコマンドです。ストアド プロシージャの実行に関する要求であれば、ストアド プロシージャへの具体的な呼び出しが表示されます。

LINQ to SQL の例

データベースからの情報へのアクセスに大きく依存する ASP.NET アプリケーションを把握するために、TIP を使用した簡単な例を見てみましょう。

TIP は特に、LINQ to SQL を使用して、外部の SQL Server データベースに格納されたデータにアクセスするアプリケーションで役に立ちます。これは、LINQ では、開発者が、物理データベースやそのパフォーマンスの特性に関する作業をあまり行わない傾向があるためです。LINQ to SQL を使用する場合、オブジェクト リレーショナル デザイナーで作成するエンティティ関係図 (E:R) を利用して、正しい構文の SQL コマンドを自動構築するために、Visual Studio がテンプレートとして使用するクラスを生成できます。

LINQ to SQL は使いやすく、SQL 言語のコーディングに関する考慮事項の大半が取り除かれるため、データベース設計、構成、およびチューニングに関連する、パフォーマンス上の重要な考慮事項が見過ごされがちです。この例で示すように、LINQ を使用すると、複数のテーブルを結合する複雑なクエリを容易に作成でき、この処理に伴うパフォーマンス上の影響を検討する必要はありません。

TIP を使用すると、LINQ to SQL が生成した実際の SQL コマンド テキストを確認でき、この SQL クエリのランタイム実行から測定データを収集できます。この SQL コマンド テキストを利用して、他のデータベース チューニング ツールにアクセスすると、特定の LINQ to SQL 操作によるパフォーマンス上の影響をさらに詳しく把握できます。

今回の例では、顧客の注文履歴を取得するために特定の顧客 ID を使用して、AdventureWorks Sales.Customer テーブルにクエリする Web フォーム アプリケーションを使用します。このクエリで使用する AdventureWorks テーブルには、Customer テーブル、SalesOrderHeader テーブル、SalesOrderDetail テーブル、StateProvince テーブルなどがあります。図 2 のオブジェクト リレーショナル デザイナー ビューをご覧ください。

Sales.Customer 情報をクエリするために使用する AdventureWorks テーブル

図 2 Sales.Customer 情報をクエリするために使用する AdventureWorks テーブル

また、注文の履歴と共に顧客の住所や電子メール アドレス情報を表示する場合は、CustomerAddress テーブル、Address テーブル、および Contact テーブルにもアクセスする必要があります。オブジェクト リレーショナル デザイナーに示されているように、AdventureWorks テーブルには、CustomerID、SalesOrder、ContactID などの主キーと外部キーが用意されており、これらのキーを使用して、テーブルを論理的に結合することができます。

LINQ to SQL を使用して、AdventureWorks の顧客のクエリを作成する C# コードを、図 3 に示します。この場合、custid が、要求される具体的な CustomerID 値です。このクエリは、select new 句に一覧されているデータ フィールドを含む、単一のデータ行が格納された、customeryquery コレクションを返します。

図 3 LINQ to SQL の顧客クエリ

var customerquery = 
  from customers in db.Customers
  from custaddrs in db.CustomerAddresses
  from addrs in db.Addresses
  where (customers.CustomerID == custid &&
         customers.CustomerID == custaddrs.CustomerID &&
         custaddrs.AddressID == addrs.AddressID)

  select new {
    customers.CustomerID,
    customers.CustomerType,
    addrs.AddressLine1,
    addrs.AddressLine2,
    addrs.City,
    addrs.StateProvince,
    addrs.PostalCode,
    customers.TerritoryID
  };

customeryquery は、次のコードを使用して、ASP.NET Web ページ上のコントロールにバインドできます。

DetailsView1.DataSource = customerquery;
DetailsView1.DataBind();

これで、この顧客の注文履歴を取得するクエリを作成できます。

var orderquery = 
  from orderhdr in db.SalesOrderHeaders
  where (orderhdr.CustomerID == custid)
  orderby orderhdr.OrderDate
  select new {
    Date = orderhdr.OrderDate.ToShortDateString(),
    orderhdr.AccountNumber,
    InvoiceNo = orderhdr.SalesOrderID,
    orderhdr.TotalDue
  };

この LINQ to SQL 操作を実行すると、orderquery には、特定の CustomerID に関連付けられた OrderHdr テーブル内の各行に対応する行が格納されます。顧客の履歴で複数の販売取引を確認できた場合、orderquery コレクションには、複数の行が格納されます。

これらのクエリは簡単に見えるでしょう。そこで、TIP を使用すると、この一見単純そうな LINQ to SQL 操作による、パフォーマンス上の影響を把握できます。

TIP データを使用したチューニング

では、customerquery について詳しく見てみましょう。実行時、LINQ to SQL は、論理データベース SELECT 操作を LINQ ステートメント内で暗黙に指定し、この LINQ ステートメントを使用して、Customers テーブル、CustomerAddresses テーブル、Addresses テーブル、および静的な StateProvince テーブルの、4 つの AdventureWorks テーブルのデータを結合する、有効な SQL コマンドを作成します。ここまで、この部分の LINQ to SQL コードは示していません。

Visual Studio プロファイラーの管理下でこのコードを実行すると、TIP インストルメンテーションは、このクエリの実行時間を報告し、この実行の待機のために Web ページが遅延した時間を測定します。これは具体的には、プロファイルの実行中に 6 回実行された操作です (図 1 参照)。

また、前にも説明したとおり、LINQ to SQL コードによって生成された SQL コマンドは、アプリケーションをプロファイルするときにも使用できます。図 4 に、この操作の実際の SQL コマンドを示します。

図 4 customerquery の SQL コマンド

SELECT [t0].[CustomerID], [t0].[CustomerType], [t2].[AddressLine1], [t2].[AddressLine2], [t2].[City], [t3].[StateProvinceID], [t3].[StateProvinceCode], [t3].[CountryRegionCode], [t3].[IsOnlyStateProvinceFlag], [t3].[Name], [t3].[TerritoryID], [t3].[rowguid], [t3].[ModifiedDate], [t2].[PostalCode], [t0].[TerritoryID] AS [TerritoryID2]
FROM [Sales].[Customer] AS [t0]
CROSS JOIN [Sales].[CustomerAddress] AS [t1]
CROSS JOIN [Person].[Address] AS [t2]
INNER JOIN [Person].[StateProvince] AS [t3] ON [t3].[StateProvinceID] = [t2].[StateProvinceID]
WHERE ([t0].[CustomerID] = @p0) AND ([t0].[CustomerID] = [t1].[CustomerID]) AND ([t1].[AddressID] = [t2].[AddressID])

SQL コマンド テキストには、LINQ によってクエリに挿入される、顧客 ID パラメーターを示すトークン (ここでは "@p0" と指定しています) が含まれていることに注意してください。

これで、SQL コマンド テキストが LINQ によって生成され、実際に使用できるようになったので、データベースの設計がクエリのパフォーマンスに与える影響を把握することができます。

このためには、この SQL コマンドを SQL Server Management Studio で実行して、実行プランを検証できます (図 5 参照)。このクエリの実行プランにアクセスするには、適切なデータベースを指定するコマンドを追加する必要があります。

USE AdventureWorks ;
GO

次に、TIP レポートから SQL コマンド テキストをコピーして、忘れないように、"@p0" トークンをデータベースの有効な CustomerID に置き換えます。続いて、このクエリの例を SQL Server Management Studio で実行し、クエリ オプティマイザーが論理要求を実行の物理プランにどのように変換したかを示す、実行プランにアクセスします。

LINQ to SQL 操作の例の実行プラン

図 5 LINQ to SQL 操作の例の実行プラン

この例では、クエリの実行プランから、SELECT ステートメントが、テーブル内の 1 行を正確に返す CustomerID フィールド上のクラスター化インデックスを使用して、Customer テーブルにアクセスしたことがわかります。SQL Server Management Studio では、マウス カーソルで操作をポイントしてプロパティを表示したり、操作を選択して右クリックし、プロパティ ウィンドウを表示したりできます。このようにして、コマンドが要求する残りの操作をそれぞれ順番に表示することができます。この後に続く 3 つの JOIN 操作により、クラスター化インデックスを使用してテーブルにアクセスし、単一の一意行を返すように、Customer を操作する最初の SELECT ステートメントが補強されます。

以上の調査から、このクエリを処理するには、AdventureWorks データベースの異なるテーブルにそれぞれ存在する、合計で 4 つの行にアクセスする必要があることがわかります。各アクセスは、テーブルの一意主キーを使用して、効率的に実行されます。

また、TIP を使用して、orderquery コードの SQL コマンドを確認し、そのコマンドを SQL Server Management Studio に追加して、実行プランを確認できます (図 6 参照)。このクエリは、CustomerID を外部キーとして使用して、OrderHdr という名前の単一のテーブルにアクセスするので、通常の非クラスター化インデックスと SalesOrderHeaderID にあるクラスター化インデックスの両方にアクセスする必要があります。

orderquery の実行プラン

図 6 orderquery の実行プラン

クエリのこの特定のインスタンスは、9 行返します。LINQ to SQL コードの orderby 句は、SQL の ORDER BY 句に変換され、SELECT の結果セット上で追加の Sort 操作が必要になります。SQL Server のプラン オプティマイザーの見積もりによると、この操作は要求を実行する際の全体のコストの 40% を占めます。

プロファイル方法の選択

TIP は、データ層の相互作用に関する特定の測定データを収集するため、既存の Visual Studio プロファイル方法を補うように設計されています。TIP は二次的なデータ収集機能で、主要なプロファイル方法を指定しなければ収集を行うことができません。TIP データは、ADO.NET を使用してデータ層と通信するアプリケーションに対してサンプリング、インストルメンテーション、および同時実行のプロファイル実行中に収集できます。

TIP データを収集するアプリケーションの主要プロファイル方法を選択する必要がある場合、どのプロファイル方法を使用すればよいでしょうか。主要プロファイル方法を選択する際の考慮事項について、いくつか説明しましょう。

パフォーマンスを調査する際、最も注目するのはデータ層の相互作用に関連する遅延でしょうか。そうであれば、主要プロファイル方法にはサンプリングを選択することをお勧めします。サンプリングは通常、最も簡単なプロファイル方法です。

パフォーマンスを調査する際、データ層の遅延にはあまり注目していない場合は、現在のコンテキストに最も適切な測定データを提供する可能性が高いプロファイル方法を選択します。たとえば、複数のスレッドの同時実行に関する問題を調査している場合は、同時実行データを収集します。CPU の制約を受けるアプリケーションに関する問題を調査している場合は、サンプリング データを収集します。主要コレクション方法の選択に関する詳細なガイダンスについては、「方法: 収集方法を選択する」という記事を参照してください。

まだデータ層のコードに精通していない場合は、ADO.NET 呼び出しを行う正確なコードを見つけるため、主要プロファイル データによる支援が必要になることがあります。TIP では、ADO.NET アウトプロセスの同期呼び出しに関する計時情報を収集する際、呼び出し履歴はキャプチャしません。アプリケーション内で、ADO.NET メソッドの呼び出しを実行するコードを把握する必要がある場合は、インストルメンテーション プロファイル方法が最も役に立ちます。サンプリング データも役に立ちますが、インストルメンテーション プロファイル方法ほど正確ではありません。

階層の相互作用の測定データと一緒にリソース競合データを収集するように選択できますが、競合データを収集するには、サンプリングよりもオーバーヘッドが大きい関数を使用する場合があります。また、競合データは、特定の ADO.NET 呼び出しを送信するコードを識別する際、役に立たない可能性があります。.NET メモリ割り当てプロファイルが必要な調査は、通常、強い影響力を持っていますが、階層の相互作用の測定データを収集しても、メリットが得られないことがあります。

サンプリング プロファイル

パフォーマンスを調査する際最も注目するのは、多くの場合、データ層の相互作用です。この場合、通常、サンプリング プロファイルを主要プロファイル方法として選択すると、最善の結果が得られます。サンプリング プロファイルは、主に、アプリケーションのパフォーマンスに与える影響が最も少ないプロファイル方法という理由から、パフォーマンスの調査に好んで使用されます。また、サンプリング プロファイルは、パフォーマンスに最も影響を与える ADO.NET 呼び出しを行うソース コードに移動する際に役立つこともわかっています。

アウトプロセスで実行されるデータ層の関数を使用すると、サンプリング プロファイル中に収集される命令実行のサンプルには、通常、ADO.NET インターフェイス間の同期呼び出しが完了するまでアプリケーションが待機した時間は反映されません。アプリケーションの実行スレッドが、このアウトプロセスの呼び出しが完了するまで待機している間、アプリケーション スレッドはブロックされ、実行サンプルは記録されません。サンプリング プロファイルを使用するときに、データ層の同期呼び出しが原因で遅延が発生するアプリケーションを把握する場合は、TIP データを収集するのが最善の方法です。

TIP が使用するインストルメンテーション プロファイルは、計時データを収集する際呼び出し履歴をキャプチャしません。そのため、階層化アプリケーションをプロファイルする際、コードにまったくなじみがなければ、データ層の呼び出しを行うコードを正確に特定するのは難しいでしょう。サンプリング プロファイルは、アプリケーション コード内で、ADO.NET インターフェイスの呼び出しを実行するコードを特定する場合にも役立つことがあります。アプリケーションで ADO.NET インターフェイス呼び出しを頻繁に行う場合、ADO.NET モジュールに費やされた時間を示すサンプル (System.Data.dll、System.Data.Linq.dll など) がいくつか収集される可能性があります。

サンプリング データを調査して、階層の相互作用の測定データと比較する際、データベースの同期呼び出しの完了を待つためにアプリケーション スレッドがブロックされている場合、スレッドのサンプリング データが収集されないことを覚えておいてください。実行中に累積されるサンプルでは、TIP が明示的に測定するアウトプロセスの遅延が除外されます。ただし、ADO.NET メソッドで収集される実行サンプルと、TIP で観察、測定される ADO.NET コマンドの数の間には、大まかな相互関係があると想定されます。このような場合、サンプリング プロファイルは、TIP で測定して報告された ADO.NET 呼び出しを行うソース コードに移動する際に役立ちます。

アプリケーションに、フォーム上のデータ バインド コントロールにバインドされる、大規模な結果セットを返す SQL クエリが含まれる場合、コントロールの DataBind メソッドで、多数の実行サンプルを確認できる可能性があることに注意してください。サンプリング プロファイルに含まれる DataBind メソッドを確認すると、ADO.NET 呼び出しを行ったソース コードに移動するのに役立つ可能性があります。

インストルメンテーション プロファイル

インストルメンテーション プロファイルを収集すると、インストルメンテーション プロファイルによって記録されるメソッドの計時データには、メソッド内でアウトプロセス呼び出しの完了を待機した時間が既に含まれています。インストルメンテーション プロファイルで記録される計時データを収集するには、インストルメンテーション用に選択されたアプリケーションの各メソッドの呼び出し時と終了時の時間を測定します。ADO.NET 呼び出しを使用して、データ層と接続しているアプリケーションのメソッドの計時データには、アウトプロセスの呼び出しを実行する際の遅延が暗黙のうちに含まれます。

TIP から収集される計時データは、アウトプロセスの遅延をそれぞれ明示的に特定して測定します。階層の相互作用のプロファイルによって測定された遅延は、メソッド内で費やされた時間全体のサブセットで、インストルメンテーション プロファイルの実行中に測定されます。このことを理解すると、階層の相互作用のプロファイルから収集された計時データを、インストルメンテーション プロファイルのメソッド レベルで収集された計時データと照合して、データ層の呼び出しを行ったメソッドを特定できます。

メソッド レベルでインストルメンテーション プロファイルを使用するだけで、アプリケーション内で ADO.NET 呼び出しを行ったコードを把握できるのであれば、ためらうことなくインストルメンテーション プロファイルを使用します。ただし、通常、インストルメンテーション プロファイルは、サンプリング プロファイルよりも面倒で、大きなオーバーヘッドが発生したり、非常に大規模な .vsp コレクション ファイルが作成される可能性があります。また、アプリケーションで、ADO.NET 関数の複数の呼び出しを実行するメソッドを使用する場合、インストルメンテーション プロファイルによって収集されたデータは、メソッド レベルで移動する場合にのみ使用でき、単一のメソッドに含まれる複数の ADO.NET 呼び出しを区別することはできません。

さらに多くのデータを収集する

多層アプリケーションを構築すると、信頼性とスケーラビリティの高い設計パターンを実現できますが、アプリケーション コンポーネントを異なるコンピューターで実行するときに、パフォーマンスの監視に関する課題が発生します。

多層アプリケーションの簡単なビューには、相互接続された層がすべて含まれないため、パフォーマンスを完全には把握できません。先ほど説明しましたが、TIP は、TIP 以外では確認できない、重要な計時データを提供できます。今回の記事の例からわかるように、この計時データは、標準的なデータベース管理ツールから提供される、他のパフォーマンス データを使って補強できます。

Mark Friedman は、マイクロソフトの Visual Studio Ultimate チームのアーキテクトです。Windows パフォーマンスに関する書籍を 2 冊執筆しており、ブログ (blogs.msdn.com/ddperf/、英語) で定期的にパフォーマンスの問題について取り上げています。

この記事のレビューに協力してくれた技術スタッフの Daryush LaqabChris Schmich に心より感謝いたします。