コードのコストを最適化するための推奨事項
次の Azure Well-Architected フレームワークのコストの最適化チェックリストの推奨事項に該当します。
CO:11 | コードのコストを最適化します。 より少ない、またはより低コストのリソースで機能要件と非機能要件を満たすためにコードを評価して変更を加えます。 |
---|
このガイドでは、コードのコストを最適化するための推奨事項について説明します。 コード最適化は、アプリケーション コードの効率、パフォーマンス、およびコスト有効性を向上させるプロセスです。 効果的なコード最適化とは、リソース消費を減らす、実行時間を最小限に抑える、および全体的なパフォーマンスを高めることを目的としてコードに変更を加えることです。
コードを最適化すると、リソース消費の増加とコスト上昇につながるおそれのある非効率な部分を特定して排除することができます。 処理に要する時間、メモリ使用量、ネットワーク オーバーヘッドを縮小でき、このことはアプリケーションのスピードと応答性の向上につながる可能性があります。 パフォーマンスが向上すれば、ユーザー エクスペリエンスがより良いものになり、システムがさらに多くのワークロードを効率的に処理できるようになります。
定義
相談 | 定義 |
---|---|
コード インストルメンテーション | 実行時にデータを収集してコードのパフォーマンスを監視するための、コード スニペットまたはライブラリをコードに追加すること。 |
コンカレンシー | 複数のプロセスを同時に実行すること。 |
データ シリアル化 | データ オブジェクトを、保存または伝送が可能な形式に変換し、後で必要に応じて元の形式に再構築するプロセス。 |
ホット パス | 1 つのプログラムのセクションのうち、きわめて重要であるか頻繁に実行されるためハイ パフォーマンスと低待機時間を必要とするもの。 |
主要な設計戦略
コードのコスト最適化とは、機能はそのままでインスタンスあたりのリソース (CPU サイクル、メモリ、ストレージなど) を減らすようにコードを改善することです。 リソースの消費を減らすことで、アプリケーションで大量のデータを処理したり、トラフィックの負荷が高い場合にコストを節約できます。
コード改善の効果は、他にもスケーリング、ライトサイジング、冗長性、スロットリングに関して最適化の作業がすでに行われているときに最大になります。 これらの基本的な要素の対応が完了した後に、コードの最適化を検討してください。
非効率なコードがあるかどうか、自分ではわからないこともあります。 サーバーレス、自動スケーリング、信頼性の機能によって、コードの非効率性が隠される可能性があります。 必要以上にコストがかかっているアプリケーション コードを特定して修正するには、次に示す戦略を参考にしてください。
コードをインストルメント化する
コードのインストルメント化とは、実行時にデータを収集してコードのパフォーマンスを監視するためのコード スニペットまたはライブラリを追加することです。 これで、開発者が主要なメトリック、たとえばリソース消費 (CPU やメモリの使用量) や実行時間についての情報を収集できるようになります。 コードをインストルメント化すると、開発者はコードのホット パスに関する分析情報を得て、パフォーマンスのボトルネックを特定できるので、効率とコスト有効性を高めるようにコードを最適化することができます。
コード分析はソフトウェア開発ライフサイクルの中の早い段階で行うのが理想的です。 コードの問題を早く見つけるほど、修正のコストは少なくなります。
このコード分析は、可能なかぎり多くの部分を自動化してください。 動的と静的のツールをコード分析に使用することによって、手作業を減らします。 ただし、このテストはまだ実稼働のシミュレーションであることを念頭に置いてください。 コードの最適化を最も明確に理解できるのは実稼働のときです。
トレードオフ: コード監視ツールを導入するとコストが増加する可能性があります。
ホット パスを最適化する
コードをインストルメント化すると、コード パスのリソース消費を測定できます。 この測定値は、ホット パスの特定に役立ちます。 ホット パスは、パフォーマンスとリソース使用に大きな影響を与えます。 これは、1 つのプログラムのセクションのうち、きわめて重要であるか頻繁に実行されるためハイ パフォーマンスと低待機時間を必要とする部分です。
ホット パスを特定するには、次のタスクを検討してください。
実行時データを分析する: コードのどの領域が大量のリソース (CPU、メモリ、I/O 操作など) を消費しているかを特定するために、実行時データを収集して分析します。 頻繁に実行される、または完了までに長い時間がかかっているコードのパターンまたはセクションを探します。
パフォーマンスを測定する: プロファイリング ツールまたはパフォーマンス テスト フレームワークを使用して、コード パスの実行時間とリソース消費を測定します。 この測定は、ボトルネックと要改善領域を特定するのに役立ちます。
ビジネス ロジックとユーザーへの影響を考慮する: コード パスの重要性を、アプリケーションの機能または重要なビジネス オペレーションとの関連性に基づいて評価します。 どのコード パスがユーザーへの価値提供またはパフォーマンス要件達成に不可欠かを判断します。
パフォーマンスに関する推奨事項のうち、お使いのプログラミング言語に固有のものを再確認してください。 これらの推奨事項に照らしてコードを評価することによって、改善が必要な領域を特定します。 コード パスの中に、パフォーマンスに影響するおそれのある不要な操作がある場合は削除します。
不要な関数呼び出しを削除する: コードの見直しを行います。 目的の機能に不可欠ではなくパフォーマンスに悪影響を与えるおそれのある関数を特定します。 たとえば、ある関数呼び出しで実行される検証が、そのコードの中ですでに行われている場合は、その不要な関数呼び出しを削除できます。
ログ記録操作を最小限に抑える: ログ記録はデバッグと分析に役立ちますが、過剰なログ記録はパフォーマンスに影響を与える可能性があります。 ログ記録操作それぞれの必要性を評価し、パフォーマンス分析に不可欠ではない不要なログ呼び出しがある場合は削除してください。
ループと条件付き処理を最適化する: コード内のループと条件付き処理を分析します。 削除可能な、不要な反復や条件を特定します。 このような構造を単純にして最適化すると、コードのパフォーマンスを向上させることができます。
不要なデータ処理を減らす: コードを見直して、不要なデータ処理操作 (冗長な計算や変換など) がないか探します。 コードの効率を高めるために、これらの不要な操作を削除します。
ネットワーク要求を最小限に抑える: コードからネットワーク要求を行う場合は、要求の数を最小限に抑えてその使用を最適化してください。 パフォーマンスを向上させるために、可能であれば要求をバッチ処理して不要なラウンド トリップを回避します。
割り当てを最小化する: 過剰なメモリ割り当てが発生している領域を特定します。 不要な割り当てを減らし、可能であれば既存のリソースを再利用するという方法でコードを最適化します。
割り当てを最小限に抑えると、メモリ効率と全体的なパフォーマンスを向上させることができます。 お使いのプログラミング言語に対して適切なメモリ管理とガベージ コレクションの戦略を使用してください。
データ構造のサイズを縮小する: データ構造 (クラスなど) のサイズを調べて、縮小が可能な領域を特定します。 データ要件を確認し、不要なフィールドまたはプロパティがある場合は除去します。 適切なデータ型を選択してデータを効率的にパッキングするという方法で、メモリ使用量を最適化します。
横断的実装を評価する: ミドルウェアやトークン チェックなどの横断的実装の影響に注目します。 これらがパフォーマンスに悪影響を与えているかどうかを評価します。
トレードオフ: コードとホット パスを最適化するには、コードの非効率性の特定における開発者の知識と経験が必要です。 このような高度なスキルを持つ個人は、その時間を他のタスクでも必要とされている可能性があります。
コンカレンシーの使用を評価する
コンカレンシーの使用を評価するには、非同期処理、マルチスレッド、またはマルチプロセッシングによってリソース使用率の最大化と支出の縮小ができるかどうかを調べる必要があります。 非同期処理、マルチスレッド、またはマルチプロセスを使用すると、同じリソースでより多くのタスクを処理できます。 ただし、オーバーヘッド増加を回避するとともにコスト有効性を維持できるように、適切に実装することがきわめて重要です。
コンカレンシーの使用が適しているかどうかを評価するには、次のガイドラインを参考にしてください。
非同期処理: 非同期処理では、ノンブロッキング実行が可能です。 たとえば、あるプロセスを開始した後に、2 番目のプロセスを最後まで実行させるために一時停止することができます。
どのコード コンポーネントまたは操作を非同期で実行できるかを判断してください。 お使いのプログラミング言語またはフレームワークを特定し、それによってサポートされている非同期プログラミング モデルを理解します。たとえば .NET での
async
/await
や、JavaScript での promise です。非同期プログラミング構成体を使用してタスクのノンブロッキング実行を可能にするように、コードを再構築してください。 長時間実行される、または I/O 集中型の操作をメイン実行スレッドから切り離します。これには非同期メソッドまたはコールバックを使用します。 お使いのプログラミング言語またはフレームワークで提供されている非同期 API またはライブラリを使用して非同期ワークフローを処理します。
マルチスレッド: マルチスレッドでは、1 つのプロセスの複数のスレッドが同時に実行されます。
コードのどのセクションを同時に、および独立して実行できるかを特定してください。 お使いのプログラミング言語またはフレームワークに固有のドキュメントまたはガイドラインを読んで、マルチスレッドのベスト プラクティスを見つけます。 タスクの並列実行を処理するために複数のスレッドまたはスレッド プールを作成します。
スレッド セーフを確実にするとともに、コードが共有リソースにアクセスするときの競合状態を防ぐために、ロック、ミューテックス、セマフォなどの同期メカニズムを実装してください。 複数スレッドの管理を効率化してコンカレンシー制御を単純にするために、高水準の抽象化 (たとえばスレッド プールやタスク ベースの並列処理ライブラリ) を使用することを検討してください。
マルチプロセッシング: マルチプロセッシングでは、複数のプロセスを並列で実行できます。 マルチスレッドよりも効率的に複数 CPU コアを活用することができます。
コード内のワークロードまたは操作が並列処理に適しているかどうかを判断してください。 お使いのプログラミング言語またはフレームワークではマルチプロセッシングに関してどのようなことができるかを調べます。 たとえば、Python では multiprocessing モジュール、Java では並列ストリームを検討します。 ワークロードを複数の独立したタスクに分割して同時に処理できるように、コードを設計します。
マルチプロセッシング API またはライブラリを使用して、並列プロセスを作成および管理してください。 ワークロードをこれらの API またはライブラリの間で分散させます。 複数のプロセス間の連携とデータ共有を可能にするために、通信メカニズムを実装します。たとえばプロセス間通信 (IPC)、共有メモリ、メッセージ パッシングなどですが、お使いのプログラミング言語またはフレームワークに応じて選択してください。
適切な SDK を使用する
コストを最適化するには、リソース使用を最適化してパフォーマンスを向上させるように設計された SDK を選択してください。 各 SDK にどのような機能があり、何ができるかを評価することが重要です。 お使いのプログラミング言語や開発環境との互換性を考慮してください。
実際のワークロードに最適な SDK を選択するには、次のガイダンスを参考にしてください。
パフォーマンス テストを実施する: SDK のリソース使用とパフォーマンスを、パフォーマンス テストを通じて比較します。 リソース最適化とパフォーマンス向上のニーズを最もよく満たすことができる SDK を選択します。 選択した SDK を、提供されているドキュメントとガイドラインに従って自分のコードベースに統合します。
リソース使用を監視してコードを最適化する: 実装済みの SDK を使用してリソース使用を監視します。 コードを最適化するための分析情報を監視と分析から収集します。
適切なオペレーティング システムを選択する
ほとんどのコーディング言語はさまざまなオペレーティング システムで実行できるため、お使いのオペレーティング システムを、その代わりとなる低コストのオペレーティング システムと比較して評価することが重要です。 代わりのオペレーティング システムで同一または類似の機能が、より低コストでサポートされる場合は、検討する価値があります。 低コストのオペレーティング システムを選ぶことによって、ライセンス料金とインフラストラクチャのコストを縮小できる可能性があります。
適切なオペレーティング システムは、ワークロードの全体的なコスト最適化に役立つ可能性があります。 実際のワークロードに適したオペレーティング システムを選択するには、次のことを試してください。
自身の要件を評価する: 実際のワークロードの具体的なニーズを理解します。これには、使用するコーディング言語やフレームワークも含まれます。 他のシステムとの依存または統合がある場合は、それも考慮してください。
互換性を考慮する: 選択するオペレーティング システムに、お使いのコーディング言語、フレームワーク、およびサードパーティ製のライブラリまたはツール (ある場合) との互換性があることを確認します。 そのオペレーティング システムのドキュメントとコミュニティ サポートを調べて、お使いのテクノロジ スタックとの互換性が良好であることを確認します。
機能を評価する: 代わりとなるオペレーティング システムでは、現在お使いのオペレーティング システムと同一または類似の機能がサポートされているかどうかを判断します。 実際のワークロードで求められる、必要な機能が提供されているかどうかを評価します。
コストの比較: オペレーティング システムに付随するコストを比較します。 ライセンス料金、サポート コスト、インフラストラクチャ要件などの要因を考慮します。 機能を損なうことなくワークロードの要件を満たすことができる、より低コストの代替製品を探します。
パフォーマンスと最適化について調べる: 代わりとなるオペレーティング システムのパフォーマンスと最適化の機能を評価します。 実際のシナリオでのパフォーマンスを理解するためのベンチマーク、ケース スタディ、またはパフォーマンス比較を探します。
セキュリティと安定性を確認する: 代わりとなるオペレーティング システムのセキュリティと安定性を評価します。 セキュリティ更新プログラム、パッチ、コミュニティ サポートに注目して、そのオペレーティング システムのメンテナンスがアクティブに行われていることと、全体的なセキュリティと安定性が保たれていることを確認します。
ベンダー サポートについて調べる: 代わりとなるオペレーティング システムではどのレベルのベンダー サポートを利用できるかを評価します。 公式のサポート チャネル、ドキュメント、ユーザー コミュニティがあり、自分が必要としているときに支援が得られるかどうかを確認します。
ネットワーク トラフィックを最適化する
ネットワーク トラバーサルの最適化とは、ワークロード コンポーネント間のネットワーク トラフィックを最小限に抑えることです。 データ転送には多くの場合、コストが伴います。 ネットワーク トラフィックを最小限に抑えると、転送が必要なデータの量を減らすと同時にコストを低減できます。
実際のワークロードを分析して、コンポーネント間での不要なデータ転送があるかどうかを特定してください。 冗長である、または重複しているデータの転送を避けて、必須の情報のみを送信してください。 たとえば、あるコンポーネントが別のコンポーネントに対して同じデータを繰り返し要求している場合は、これが最適化の候補になります。 不要な呼び出しを減らす、または要求をバッチ処理するようにコードをリファクターすると、転送されるデータを最小限に抑えることができます。 アプリケーションからオブジェクトまたはデータ構造の全体が送信されていても、必要なフィールドはごく少数ということもあります。 必要なデータのみを送信するようにコードを最適化すると、各データ転送のサイズを最小限に抑えることができます。
ネットワーク プロトコルを最適化する
ネットワーク プロトコルは、ネットワーク通信の効率を左右します。 ネットワーク プロトコルを最適化すると、データ転送の全体的な効率を高めるとともにリソース消費を減らすことができます。
次の推奨事項を検討してください。
効率的なプロトコルを選ぶ: データ転送速度とオーバーヘッド最小化という点での効率性で知られているプロトコルを選択します。 たとえば、HTTP/1.1 よりも HTTP/2 などのプロトコルを使用することを検討してください。 これらのプロトコルはパフォーマンスが向上するように設計されており、待機時間が短縮するとともにデータ転送が最適化されます。 これらのプロトコルをアプリケーションで使用するには、ライブラリとフレームワークを使用します。
圧縮をサポートする: 転送されるデータのサイズを縮小するために、使用するネットワーク プロトコルの中で圧縮メカニズムを実装します。 圧縮すると、ネットワークを介して伝送されるデータの量を大幅に縮小でき、このことはパフォーマンス向上と帯域幅使用量の縮小につながります。 サーバー側での圧縮の有効化は一般的に、アプリケーション コードまたはサーバー構成の中で行われます。
接続プーリングを利用する: 接続をプール化すると、確立済みのネットワーク接続を再利用できるので、要求のたびに新しい接続を確立する場合のオーバーヘッドを減らすことができます。 接続プーリングを利用すると、接続のセットアップと破棄のオーバーヘッドが回避されるため、ネットワーク通信の効率を向上させることができます。 ワークロードのニーズを満たすように接続プーリングのライブラリまたはフレームワークを選択して構成してください。
他の最適化を実装する: 実際のワークロードとネットワーク環境に固有の、その他の最適化にはどのようなものがあるかを調べます。 たとえば、コンテンツ キャッシング、負荷分散、トラフィック シェーピングを使用してネットワーク トラバーサルをさらに最適化することができます。
ネットワーク オーバーヘッドを最小化する
ワークロードのコンポーネント間のネットワーク トラフィックとデータ転送の量を最小限に抑えてください。 ネットワーク オーバーヘッドを減らすと、データ エグレスとイングレスに付随するコストを低減するとともに全体的なネットワーク パフォーマンスを向上させることができます。
次の手法を検討してください。
冗長な要求を減らす: コードを分析して、重複している、または不要な要求があるかどうかを特定します。 同じデータに対する要求を何度も行う代わりに、データを 1 回取得して必要に応じて再利用するように、コードに変更を加えます。
データ サイズを最適化する: コンポーネント間またはシステム間で伝送されるデータを調査して、そのサイズを最小化する機会を探します。 伝送前にデータを圧縮する、またはより効率的なデータ形式を使用するなどの手法を検討してください。 データ サイズを縮小すると、ネットワーク帯域幅の使用量を減らすとともに全体的な効率を向上させることができます。
要求をバッチ処理する: 該当する場合は、複数の小さな要求を 1 つの大きな要求にまとめてバッチ処理することを検討してください。 バッチ処理すると、複数の接続確立のオーバーヘッドが減るとともに全体的なデータ伝送量が減少します。
データ シリアル化を使用する: データ シリアル化とは、複雑なデータ構造またはオブジェクトをネットワーク上で伝送しやすい、または永続的ストレージ システムに格納しやすい形式に変換するプロセスです。 この戦略を取る場合は、データを標準化された形式で表すことになるため、データの伝送、処理、受信側での再構築を効率的に行うことができます。
シリアル化形式を選択するときは、コンパクトかつ高速で、実際のワークロードの要件に適したものを選択します。
シリアル化の形式 説明 Protocol Buffers (protobuf) このバイナリ シリアル化形式では、構造化データのエンコードとデコードを効率的に行うことができます。 型指定された定義ファイルを使用してメッセージの構造が定義されます。 MessagePack このバイナリ シリアル化形式は、ネットワーク上でのコンパクトな伝送を目的としています。 さまざまなデータ型がサポートされており、シリアル化と逆シリアル化の実行の速さが特徴です。 JavaScript Object Notation (JSON) このデータ シリアル化形式は人間が判読可能で扱いやすく、広く使用されています。 JSON はテキスト ベースであり、広範なクロスプラットフォーム サポートが特徴です。 Binary JSON (BSON) このバイナリ シリアル化形式は JSON に似ていますが、シリアル化と逆シリアル化を効率的に行うように設計されています。 BSON には、JSON で扱うことのできない追加のデータ型が含まれています。 選択したシリアル化形式に応じて、オブジェクトまたはデータ構造をその形式にシリアル化する、および逆シリアル化して元の形式に戻すためのロジックを実装する必要があります。 このロジックは、その形式のシリアル化が可能なライブラリまたはフレームワークを使用して実装できます。
データ アクセスを最適化する
データ アクセスの最適化とは、データの取得と保存のパターンと手法を効率化することであり、その目的は不要な操作を最小限に抑えることです。 データ アクセスを最適化すると、リソース使用量が減り、データ取得が減り、データ処理の効率が向上するため、コストを節約できます。 データのキャッシュ、効率的なデータ クエリ、データ圧縮などの手法を考えてみてください。
キャッシュ メカニズムを使用する
キャッシュとは、頻繁にアクセスされるデータを、そのデータを必要とするコンポーネントの近くに保存することです。 この手法を利用すると、データはネットワークを介して取得されるのではなくキャッシュから渡されるため、ネットワーク トラバーサルの必要性が縮小します。
次のキャッシュ メカニズムを検討してください。
外部キャッシュを使用する: よく利用されているキャッシュ ソリューションの 1 つは、コンテンツ配信ネットワークです。 静的コンテンツが利用者の近くでキャッシュされるため、待機時間を最小限に抑えるとともにネットワーク トラバーサルを減らすのに役立ちます。
キャッシュ パラメーターをチューニングする: キャッシュの利点を最適化すると同時に潜在的な欠点を最小限に抑えるようにキャッシュのパラメーター、たとえば Time to Live (TTL) を構成します。 TTL が適切に設定されていれば、キャッシュされたデータは常に最新で関連性のある状態になります。
インメモリ キャッシュを使用する: 外部キャッシュ ソリューションに加えて、インメモリ キャッシュをアプリケーション内で実装することを検討してください。 インメモリ キャッシュは、アイドル状態のコンピューティング リソースの活用と、割り当て済みリソースのコンピューティング密度の向上に役立ちます。
データベース トラフィックを最適化する
アプリケーションからデータベースへの通信の効率を高めることができます。 データベース トラフィックの最適化に関する主な考慮事項と手法を次に示します。
インデックスを作成する: インデックス作成とは、データ取得の速度を上げるデータ構造を作成するプロセスです。 クエリ実行の対象となる頻度が高い列にインデックスを作成すると、クエリの実行にかかる時間を大幅に短縮できます。 たとえば、ユーザーのテーブルにユーザー名の列がある場合に、このユーザー名列にインデックスを作成すると、特定のユーザー名を検索するクエリの速度を上げることができます。
アクセスされる頻度が高い列を特定し、データ取得の速度を上げるためにその列にインデックスを作成してください。 既存のインデックスの分析と最適化を定期的に行い、引き続き効果を発揮していることを確認します。 インデックスの過剰作成は、挿入と更新の操作に悪影響を及ぼす可能性があるため避けてください。
クエリを最適化する: 効率的なクエリを設計するには、具体的なデータ要件を考慮するとともに不要なデータ取得を最小限に抑えます。 まず、テーブル間のリレーションシップに基づいて適切な結合の種類 (たとえば内部結合や左結合) を使用します。 パフォーマンスを向上させるためのクエリ最適化手法として、クエリ ヒント、クエリ プラン分析、クエリの書き換えなどを使用します。
クエリの結果をキャッシュする: 頻繁に実行されるクエリの結果をメモリまたはキャッシュに保存できます。 その後で同じクエリを実行するときは結果をキャッシュから取得できるので、高コストのデータベース操作が不要になります。
オブジェクト リレーショナル マッピング (ORM) フレームワークを使用する: ORM の機能 (遅延読み込み、キャッシュ、バッチ処理など) を使用して、データ取得を最適化するとともにデータベース ラウンド トリップを最小限に抑えます。 Entity Framework for C# や Hibernate for Java などの ORM フレームワークを使用します。
ストアド プロシージャを最適化する: ストアド プロシージャのロジックとパフォーマンスを分析して最適化します。 目標は、ストアド プロシージャ内での不要な計算や冗長クエリを回避することです。 リソース消費を最小限に抑えるために、一時テーブル、変数、カーソルの使用を最適化してください。
データを組織化する
効率的なアクセスと取得を目的としてデータを組織化するには、パフォーマンスを最大化してリソース消費を最小限に抑えるようにデータを構造化して保存する必要があります。 これによってクエリ応答時間を短縮し、データ転送コストを縮小し、ストレージ使用率を最適化することができます。
データを効率的に組織化するための主な手法を次に示します。
パーティション: パーティション分割とは、大きなデータセットを、パーティションと呼ばれる小さな管理しやすいサブセットに分割することです。 各パーティションを別々に保存できるので、並列処理が可能になり、クエリのパフォーマンスも向上します。 たとえば、データを特定の値の範囲に基づいて、またはデータを複数のサーバーに分散させることによってパーティション分割できます。 この手法を利用すると、スケーラビリティを向上させ、競合を減らし、リソース使用率を最適化することができます。
シャード: シャーディングとは、データを水平方向に分割して複数のデータベース インスタンスまたはサーバーに分散させるという手法です。 各シャードにはデータのサブセットが格納されており、これらのシャードに対するクエリを並列で処理できます。 シャーディングによってワークロードが分散し、各クエリでアクセスされるデータの量が減るため、クエリのパフォーマンスを向上させることができます。
圧縮: データ圧縮とは、ストレージの所要量を最小限に抑えるとともにデータ転送の効率を向上させることを目的として、データのサイズを小さくすることです。 データが圧縮されていれば占有するディスク領域が小さくなるため、ストレージ コストの節約が可能になります。 圧縮されたデータはネットワーク上で転送されるときの時間も短くなるため、データ転送コストを縮小できます。
たとえば、顧客情報が 1 つの大きなデータセットに格納されているというシナリオを考えてみます。 このデータを、顧客の地域または人口統計学的情報に基づいてパーティション分割すると、ワークロードを複数のサーバーに分散してクエリのパフォーマンスを向上させることができます。 また、データを圧縮するとストレージ コストを縮小するとともにデータ転送の効率を向上させることができます。
ソリューション設計を最適化する
ワークロードのアーキテクチャを評価して、リソース最適化の機会を特定してください。 目標は、適切なサービスを適切なジョブに使用することです。
この目標を達成するには、使用するリソースを減らすようにアーキテクチャの一部を再設計することが必要になる可能性があります。 サーバーレスまたはマネージド サービスを検討するとともに、リソースの割り当てを最適化してください。 アーキテクチャを最適化すると、機能要件と非機能要件を満たすと同時にインスタンスあたりのリソース消費量を減らすことができます。
設計パターンを使用する
設計パターンは、開発者が繰り返し直面する設計の問題を解決するのに役立つ再利用可能なソリューションです。 これを利用すると、効率的で保守しやすくスケーラブルなコードの設計を、構造化されたアプローチで行うことができます。
設計パターンを利用すると、効率的なリソースの割り当てと管理のガイドラインが得られるため、システム リソースの使用を最適化するのに役立ちます。 たとえば、"サーキット ブレーカー" パターンでは、障害への対応と復旧を統制された方法で行うためのメカニズムが提供されるので、不要なリソース消費の防止に役立ちます。
コードのコスト最適化に関しては、設計パターンは次のように役立ちます。
開発時間を短縮する: 設計パターンは、一般的な設計上の問題に対する実証済みの解決方法であるため、開発に要する時間を減らすことができます。 確立されたパターンに従うことで、開発者は繰り返し作業を回避して自分のアプリケーション固有の要件の実装に集中できます。
保守性を向上させる: 設計パターンに従うと、モジュール型で構造化されたコードを作成できるので、理解しやすく、変更と保守も簡単になります。 デバッグとメンテナンスの労力が減るという点で、コスト節約につながる可能性があります。
スケーラビリティとパフォーマンス: 設計パターンは、スケーラブルでパフォーマンスの高いシステムの設計に役立ちます。 "キャッシュ アサイド" パターンのようなパターンでは、頻繁にアクセスされるデータをキャッシュすることで高コストの計算や外部呼び出しの必要性が減るため、パフォーマンスを向上させることができます。
設計パターンを実装するには、開発者は各パターンの原則とガイドラインを理解してコードに適用する必要があります。 問題に対して適切なパターンを特定する、その構造とコンポーネントを理解する、およびそのパターンを全体的な設計に統合することを検討してください。
ドキュメント、チュートリアル、サンプル コードなど、さまざまなリソースが用意されています。 これらのリソースは、開発者が設計パターンの学習と実装を効果的に行うのに役立ちます。
構成を変更する
ワークロード構成の見直しと更新を定期的に行ってください。これは、その時点での要件に確実に整合させるためです。 リソースのサイズ設定と構成設定をワークロードの需要に基づいて調整することを検討してください。 構成を最適化すると、リソースを効果的に割り当ててオーバープロビジョニングを回避できるので、コストを節約できます。
アーキテクチャをリファクターする
ワークロード アーキテクチャを評価し、リソース消費の最適化を目的としてコンポーネントをリファクタリングまたは再設計する機会を特定してください。 マイクロサービス アーキテクチャの採用、"サーキット ブレーカー" パターンの実装、サーバーレス コンピューティングの使用などの手法を検討してください。 アーキテクチャを最適化すると、より良いリソース使用率とコスト効率を達成できます。
リソースのサイズを変更する
ワークロードのリソース使用率の監視と分析を継続的に行ってください。 観察されたパターンと傾向に基づいて、リソースのサイズ設定と構成設定を調整することによってリソース消費を最適化します。
仮想マシンのライトサイジング、メモリ割り当ての調整、ストレージ容量の最適化を検討してください。 リソースのサイズを適切に設定すると、過小使用や過剰プロビジョニングに伴う不要なコストを回避できます。
トレードオフ: コードとアーキテクチャの手直しが、その時点のプロジェクト スケジュールに収まらないこともあり、スケジュール遅延や超過コストにつながる可能性があります。
Azure ファシリテーション
コードのインストルメント化: Azure には、監視とログのツールとして Azure Monitor、Application Insights、Log Analytics などがあります。 これらのツールを使用すると、コードのパフォーマンスと振る舞いをリアルタイムで追跡して分析できます。
ホット パスの特定と最適化: Application Insights と Application Insights Profiler では、実行時間とリソース使用状況を分析できるので、コード内のホット パスを特定して最適化するのに役立ちます。 Profiler を使用して、不要なメモリ割り当てを最小限に抑えてメモリ使用量を最適化することができます。
適切な SDK の使用: Azure の SDK は多数の言語で提供されており、パフォーマンスが高く使いやすいように最適化されています。 これらの SDK では、Azure サービスと相互作用する関数とライブラリが事前構築されているため、独自の実装の必要性が減ります。
ネットワーク トラバーサルの最適化: Azure のさまざまなサービスで HTTP/2 や QUIC などの高速ネットワーク プロトコルがサポートされているため、サービスとアプリケーションの間で効率的に通信できます。
Azure Database for PostgreSQL - フレキシブル サーバーなどの Azure サービスで接続プーリングがサポートされています。
Azure ではバッチ処理がさまざまなサービスでサポートされているため、複数の操作をグループ化して単一の要求で実行することができます。 バッチ処理を利用すると効率が大幅に向上し、ネットワークのオーバーヘッドが縮小します。
データのシリアル化に関して、Azure では JSON や XML などのさまざまなシリアル化形式がサポートされています。 データ サイズ、パフォーマンス要件、相互運用性のニーズに基づいて、適切なシリアル化形式を選択してください。
データ アクセスの最適化: Azure では、キャッシュ サービスとして Azure Cache for Redis などが提供されています。 キャッシュを使用すると、頻繁にアクセスされるデータをアプリケーションの近くに保存できるので、その結果として取得に要する時間が短くなり、バックエンドの負荷が減少します。
インデックス作成とクエリ最適化: Azure SQL Database や Azure Cosmos DB などの Azure サービスには、クエリのパフォーマンスを最適化するためのインデックス作成機能があります。 適切なインデックス作成戦略を選択してクエリを最適化すると、データ取得の全体的な効率を向上させることができます。
オブジェクト リレーショナル マッピング (ORM): Azure では、Entity Framework などの ORM フレームワークがサポートされています。 このようなフレームワークを利用すると、オブジェクト指向コードとリレーショナルまたは NoSQL データベースとの間のデータ アクセスとマッピングが単純になります。
ストアド プロシージャの最適化: Azure SQL Database などの Azure サービスを使用して、ストアド プロシージャを作成および最適化できます。 ストアド プロシージャを利用すると、ネットワーク ラウンド トリップが減り、SQL ステートメントがプリコンパイルされるため、パフォーマンスを向上させることができます。
パーティション分割とシャーディング: Azure では、Azure Cosmos DB や Azure SQL Database などのサービスでパーティション分割とシャーディングの機能が提供されています。 パーティション分割を使用すると、スケーラビリティとパフォーマンス最適化を目的としてデータを複数のノードに分散させることができます。
データの圧縮: Azure サービスでは、データ圧縮手法として GZIP や DEFLATE などがサポートされています。
アーキテクチャの最適化: Azure では、スケーラブルで回復性があり、パフォーマンスの高いアプリケーションを設計するためのアーキテクチャ ガイダンスと設計パターンが提供されています。 詳細については、設計パターンに関するページを参照してください。
関連リンク
- Azure Monitor
- Application Insights
- Log Analytics
- Application Insights Profiler
- 接続プール
- Azure Database for PostgreSQL - フレキシブル サーバーでの接続プーリング
- Azure SQL Database でのインデックス チューニング
- Azure Cosmos DB でのインデックス作成ポリシー
- Azure Cosmos DB でのパーティション分割
- Azure SQL Database でのパーティション分割
コスト最適化チェックリスト
レコメンデーションの完全なセットを参照してください。