Azure Database for MySQL - フレキシブル サーバーのパフォーマンスを最適化するためのベスト プラクティス
適用対象: Azure Database for MySQL - 単一サーバー Azure Database for MySQL - フレキシブル サーバー
重要
Azure Database for MySQL シングル サーバーは廃止パスにあります。 Azure Database for MySQL フレキシブル サーバーにアップグレードすることを強くお勧めします。 Azure Database for MySQL フレキシブル サーバーへの移行の詳細については、Azure Database for MySQL シングル サーバーの現状に関するページを参照してください
Azure Database for MySQL フレキシブル サーバーの使用時に最高のパフォーマンスを得る方法について説明します。 Microsoft は、プラットフォームに新しい機能を追加していく中で、このセクションで詳しく説明するレコメンデーションを改善していきます。
物理的な近接
アプリケーションとデータベースを同じリージョンにデプロイしていることを確認します。 パフォーマンス ベンチマークの実行を開始する前のクイック チェックとして、簡単な SELECT 1 クエリを使用して、クライアントとデータベース間のネットワーク待機時間を確認します。
Web アプリケーションとその関連データベースなどのリソースが異なるリージョンで実行されている場合、それらのリソース間の通信に待機時間が長くなる可能性があります。 アプリケーションとデータベースを別々のリージョンに配置することで起こりうるもう 1 つの影響は、 送信データ転送コストに関連します。
コスト最適化デプロイでアプリケーションのパフォーマンスと信頼性を向上させるには、Web アプリケーション サービスと Azure Database for MySQL フレキシブル サーバー リソースを同じリージョンと可用性ゾーンに配置することを強くお勧めします。 このコロケーションは、待機時間の影響を受けやすいアプリケーションに最適であり、リソースが密接にペアになっているため、最適なスループットも提供します。
Accelerated Networking
Azure 仮想マシン、Azure Kubernetes、または App Services を使用する場合は、アプリケーション サーバー用に高速ネットワークを使用します。 高速ネットワークは VM へのシングル ルート I/O 仮想化 (SR-IOV) を可能にします。これにより、ネットワークのパフォーマンスが大幅に向上します。 この高パフォーマンスのパスによってデータパスからホストがバイパスされ、サポートされる VM タイプの最も要件の厳しいネットワーク ワークロードで使用した場合でも、待ち時間、ジッター、CPU 使用率が軽減されます。
接続の効率
新しい接続を確立することは、常にコストが高く時間のかかる作業です。 アプリケーションは、データベース接続を要求するときに、新しい接続の作成よりも、既存のアイドル状態のデータベース接続の割り当てを優先します。 適切な接続を実践するためのいくつかのオプションを次に示します。
ProxySQL: 組み込みの接続プールを提供する ProxySQL を使用します。また、アプリケーション コードへの変更によって、必要に応じて、複数の読み取りレプリカに対してワークロードを負荷分散させます。
Heimdall Data Proxy:また、ベンダー中立の専用プロキシ ソリューションである Heimdall Data Proxy を使用することもできます。 クエリのキャッシュと、レプリケーションのラグ検出を使用した読み取りまたは書き込みの分割がサポートされています。 Heimdall Proxy を使用して MySQL のパフォーマンスを向上させる方法も参照してください。
永続的または有効期間が長い接続:: アプリケーションで、通常、実行時間が 5 ms から 10 ms 未満の短時間のトランザクションまたはクエリが使用される場合、短時間の接続を永続的な接続に置き換えます。 短時間の接続を永続的な接続に置き換えるには、コードをわずかに変更するだけで済みますが、多くの標準的なアプリケーション シナリオでのパフォーマンス向上の点から見ると大きな影響があります。 トランザクションが完了したときにタイムアウトするか接続を閉じるように設定してください。
レプリカ: レプリカを使用する場合は、ProxySQL を使用して、プライマリ サーバーと読み取り可能なセカンダリ レプリカ サーバーの間で負荷を分散させます。 ProxySQL の設定方法を参照してください。
接続のプール
接続プールは、データベース接続の作成と割り当てを管理し、接続の急増からデータベースを保護するメカニズムです。 アプリケーションが比較的短時間で多数の接続を開き、接続の有効期間が短い場合は、接続プールを検討してください。 このような種類の接続は、たとえば、1 秒あたり数百または数千以上発生する可能性があり、接続の合計有効期間と比較して、接続の確立と終了にかかる時間が大幅に長くなります。
アプリケーションの開発フレームワークで接続プールがサポートされていない場合は、代わりに、アプリケーションとデータベース サーバーの間で ProxySQL や Heimdall プロキシなどの接続プロキシを使用します。
接続のスケーリングの処理
変動する需要に合わせて Web アプリケーションをスケーリングする一般的な方法は、アプリケーション サーバーを追加および削除することです。 各アプリケーション サーバーは、データベースとの接続プールを使用できます。 この方法では、アプリケーション サーバーの数に対して、データベース サーバーの接続の合計数が増加します。 たとえば、データベース サーバーに 10 台のアプリケーション サーバーがあり、それぞれが 100 のデータベース接続用に構成されている場合、1,000 のデータベース接続が提供されます。 ユーザー アクティビティの増加やピーク時にアプリケーション ワークロードがスケーリングされ、さらに 50 台のアプリケーション サーバーが追加された場合、データベース接続の合計は 6,000 になります。 通常、これらの接続のほとんどは、アプリケーション サーバーによって生成された後、アイドル状態になります。 アイドル状態の接続ではリソース (メモリと CPU) が消費されて開いたままになるため、データベースのスケーラビリティが影響を受ける可能性があります。
その他の潜在的な課題として、データベース サーバーへの接続の合計数の処理が含まれます。 これは、データベース サーバーに接続されているアプリケーション サーバーの数によって決まり、各サーバーが独自の接続セットを作成します。 これらのシナリオでは、アプリケーション サーバーの接続プールを調整することを検討してください。 データベース サーバー側の接続に肥大化がないように、各プール内の接続の数を許容できる最小数に減らしてください。 これは、アプリケーションの成長に対処するための永続的なソリューションではなく、アプリケーション サーバーのスケーリングの影響に対抗するための短期的な救済策と考えてください。
長期的なソリューションとして、データベース サーバーとアプリケーション サーバーの間に ProxySQL や Heimdall プロキシなどの接続プロキシを導入します。 これは、プロキシが次の場合に役立ちます。
- 固定数の接続を使用して、データベース サーバーへの接続を確立します。
- アプリケーション接続を受け入れ、潜在的な接続ストームのバッファーとして機能します。
Azure Functions プロキシは、クエリ キャッシュ、接続バッファリング、クエリの書き換え/ルーティング、負荷分散などの他の機能を提供できます。 スケーラビリティをさらに高める場合は、複数のプロキシ インスタンスを使用することを検討してください。
フォールト トレランスと高速復旧のための接続処理
フォールト トレランスと高速復旧のためにアプリケーションと環境を設計する場合は、データベース環境で接続の中断やハードウェア障害が発生する可能性があることを考慮してください。 また、インスタンス サイズのスケーリング、修正プログラムの適用、手動フェールオーバーの実行などの運用アクションの必要性も覚えておいてください。
たとえば、データベース サーバーが 1 分以内にフェールオーバーを完了するが、アプリケーション側で DNS TTL が長すぎるなどの理由で、アプリケーションが数分間停止するシナリオを考えてみましょう。 このような場合は、TTL 値を小さくするだけで復旧時間が短縮されます。または、アプリケーションとデータベース サーバーの間に接続プロキシを統合すると、このようなエラーの処理に役立ちます。
パーティション分割
運用ワークロードで非常に大きなテーブルを使用する場合、パーティション分割は、データベースのパフォーマンスを向上させ、メンテナンスを容易にする優れた方法です。 パーティション分割により、大きなテーブルの管理が容易になります。この方法では、パーティションを追加したり削除したりして、大規模なテーブルを効果的に管理できます。 パーティション分割は、テーブルごとの内部ロックやインデックスごとの内部ロックなどの内部構造の競合を緩和することで、エンジンのスケーリングにも役立ちます (たとえば、InnoDB のbtr_search_latch を考慮してください)。
たとえば、5 つのパーティションを追加すると、基本的に、アクティビティが多い大きなテーブルを、より小さく効率的な 5 つのテーブルに分割できます。 これは、主な操作がテーブルの主キー検索である場合に主に役立ちます。これにより、クエリで "パーティションの排除" を利用できます。 ただし、パーティション分割は、テーブル スキャンの観点からも役立ちます。
パーティション分割には利点もありますが、パーティション テーブルでの外部キーのサポートがされていない、クエリ キャッシュの不足など、いくつかの制限があることに注意してください。これらの制限の完全なリストについては、MySQL リファレンス マニュアルの「パーティション分割に関する制限事項と制約事項」の章を参照してください。
読み取りと書き込みの分離
ほとんどのアプリケーションは主にデータベースから読み取られますが、書き込みを伴う操作の割合はごくわずかです。 接続プールに対して計算したプライマリ データベースのアクティブな接続数には、読み取りトラフィックが含まれている可能性があります。 可能な限り多くのクエリを読み取りレプリカにオフロードし、プライマリ書き込み可能なインスタンスへのアクセスを確保すると、プライマリ データベースの負荷を増やすことなく、アプリケーション サーバーによって実行される全体的なデータベース アクティビティの量が増加します。 レポートなどの実行時間の長いクエリに対して、少なくとも読み取りレプリカにまだアクセスしていない場合は、レポートまたは分析を読み取りレプリカに直ちに移動することを検討する必要があります。
レプリケーションの非同期性により、レプリカがプライマリよりわずかに遅れているため、読み取りレプリカの大規模な使用には、より慎重な検討が必要になる場合があります。 マイナー コードを変更してレプリカからの読み取りで提供できるアプリケーションの領域をできるだけ多く見つけます。 また、キャッシュに関するより高いレベルでこのメソッドを適用する必要があります。読み取り専用のコンテンツの多くを提供するか、Azure Cache for Redis などの専用キャッシュ層からコンテンツをゆっくりと変更します。
書き込みのスケーリングとシャーディング
時間の経過と共にアプリケーションが進化し、新しい機能が追加されます。 便宜上または一般的な方法では、テーブルはプライマリ データベースに追加されます。 データベースのトラフィック負荷の増加に対処するには、アプリケーションの領域を特定して、別のデータベースに簡単に移動できるようにし、データベースを水平方向にシャーディングまたは垂直方向に分割することを検討します。
データベースを水平方向にシャーディングするには、アプリケーション スキーマの複数のコピーを別々のデータベースに作成し、顧客 ID、地域、またはその他の顧客ごとの属性またはテナント属性に基づいて顧客とすべての関連データを分離します。 これは、個々の顧客が小さく、アプリケーションの負荷が数百万人の顧客の集計使用量からである SaaS または B2C アプリケーションに非常に適しています。 ただし、顧客のサイズが異なり、個々の大規模な顧客が特定のシャードのトラフィック負荷を支配する可能性がある B2B アプリケーションでは、より困難です。
データベースを機能的にシャーディングして負荷を垂直方向に分割し、 個別のアプリケーション ドメイン (またはマイクロ サービス) を独自のデータベースに移動します。 これにより、負荷がプライマリ データベースから、個別のサービスごとのデータベースに分散されます。 単純な例には、大量に読み込まれた注文テーブルと同じデータベースに存在する必要のないログ テーブルまたはサイト構成情報が含まれます。 より複雑な例としては、注文やフルフィルメント ドメインとは別に、顧客とアカウントのドメインを分割するなどがあります。 場合によっては、アプリケーションの変更が必要になる場合があります。たとえば、電子メールまたはバックグラウンド ジョブ キューを自己完結型に変更し、顧客テーブルまたは注文テーブルへの結合に依存しないようにする必要があります。 既存のテーブルとデータを新しいプライマリ データベースに移動するには、Azure Database for MySQL フレキシブル サーバーの読み取りレプリカを使用し、レプリカを昇格させ、アプリケーションの一部を新しく作成された書き込み可能なデータベースにポイントします。 新しく作成されたデータベースでは、元のプライマリと同様に、接続プールへのアクセスを制限し、クエリを調整し、独自のレプリカで負荷を分散する必要があります。
データ インポートの構成
- データのインポート操作を開始する前に、インスタンスをより大きい SKU サイズに一時的にスケーリングし、その後、インポートが成功したらそれをスケールダウンできます。
- オンラインまたはオフラインの移行で Azure Database Migration Service (DMS) を使用して、最小限のダウンタイムでデータをインポートできます。
Azure Database for MySQL フレキシブル サーバーのメモリに関する推奨事項
Azure Database for MySQL フレキシブル サーバーのパフォーマンスのベスト プラクティスは、作業セットがほぼ完全にメモリ内に存在するように、十分な RAM を割り当てることです。
- Azure Database for MySQL フレキシブル サーバーのメトリックを使用して、メモリの使用率が制限に達しているかどうかを確認します。
- このような数値に対してアラートを設定して、サーバーが制限に達したときに、迅速に対処して修正できるようにします。 定義されている制限に基づいて、データベースの SKU をスケールアップして、より大きいコンピューティング サイズにするか、またはより適切な価格レベルにすることで、パフォーマンスが大幅に向上するかどうかを確認します。
- スケーリング操作の後に、パフォーマンスの数値が大幅に低下しなくなるまでスケールアップします。 DB インスタンスのメトリックの監視の詳細については、Azure Database for MySQL フレキシブル サーバー DB のメトリックに関する記事を参照してください。
InnoDB バッファー プールのウォームアップの使用
Azure Database for MySQL フレキシブル サーバー インスタンスを再起動した後、テーブルのクエリが実行されるときにストレージ内にあるデータ ページが読み込まれるため、クエリの初回実行時の待ち時間が長くなり、パフォーマンスが低下します。 これは、待機時間の影響を受けやすいワークロードでは許容できない可能性があります。
InnoDB バッファー プールのウォームアップを利用すると、DML または SELECT 操作が対応する行にアクセスするのを待機するのではなく、再起動の前にバッファー プール内にあったディスク ページを再読み込みするので、ウォームアップ期間を短縮できます。
Azure Database for MySQL フレキシブル サーバー インスタンスを再起動した後のウォームアップ期間を短縮できます。これは、InnoDB バッファー プール サーバー パラメーターを構成すると得られるパフォーマンス上の利点です。 InnoDB は、サーバーのシャットダウン時に各バッファー プールで最近使用されたページを一定の割合で保存し、サーバーの起動時にこれらのページを復元します。
また、パフォーマンスの向上は、サーバーの起動時間が長くなるという代償を伴うことに注意してください。 このパラメーターを有効にすると、サーバーにプロビジョニングされている IOPS に応じて、サーバーの起動と再起動にかかる時間が長くなることが予想されます。
その間はサーバーが利用できないため、起動/再起動のパフォーマンスが許容できるように、再起動時間をテストし監視することをお勧めします。 プロビジョニングされた IOPS が 1000 未満である場合 (つまり、プロビジョニングされたストレージが 335 GB 未満の場合) は、このパラメーターを使用しないことをお勧めします。
サーバーのシャットダウン時にバッファー プールの状態を保存するには、サーバー パラメーター innodb_buffer_pool_dump_at_shutdown
を ON
に設定します。 同様に、サーバー起動時にバッファー プールの状態を復元するには、サーバー パラメーター innodb_buffer_pool_load_at_startup
を ON
に設定します。 サーバー パラメーター innodb_buffer_pool_dump_pct
の値を下げて微調整すると、起動/再起動時間への影響を制御できます。 既定では、このパラメーターは 25
に設定されます。
注意
InnoDB バッファー プールのウォームアップ パラメーターは、最大 16 TB のストレージを持つ汎用ストレージ サーバーでのみサポートされています。 詳しくは、Azure Database for MySQL フレキシブル サーバーのストレージ オプションに関する記事をご覧ください。