データベースのパフォーマンスの改善

アプリの Firebase Realtime Database のパフォーマンスを改善するには、いくつかの方法があります。Realtime Database のパフォーマンスを最適化するためにできることを確認するには、さまざまな Realtime Database モニタリング ツールを使用してデータを収集し、それに応じてアプリまたは Realtime Database の使用方法を変更します。

Realtime Database のパフォーマンスをモニタリングする

Realtime Database のパフォーマンスに関するデータを収集するには、必要な粒度に応じていくつかの異なるツールを使用します。

  • 概要データ: インデックス付けされていないクエリのリストや読み取り / 書き込みオペレーションの概要をリアルタイムで取得するには、プロファイラ ツールを使用します。
  • 使用料金の見積もり: 使用料金やおおまかなパフォーマンス指標を確認するには、Firebase コンソール使用状況の指標を使用します。
  • 詳細データ: データベースのパフォーマンスの推移を詳細に調べるには、Cloud Monitoring を使用します。

指標ごとのパフォーマンスの向上

データを収集したら、改善するパフォーマンス領域に基づいて、次のベスト プラクティスと戦略を検討してください。

パフォーマンス改善戦略の概要
指標 説明 おすすめの方法
負荷 / 使用率 任意の時点でリクエストの処理に使用されるデータベースの容量を最適化します(**Load** または **io/database_load** 指標に反映されています)。 データ構造を最適化する
データベース間でデータをシャーディングする
リスナーを効率化する
クエリベースのルールを使用してダウンロードを制限する
接続を最適化する
アクティブな接続 データベースに対するアクティブな同時接続数を調整し、接続数の上限の 200,000 を超えないようにします。 データベース間でデータをシャーディングする
新規接続数を減らす
送信帯域幅 データベースからのダウンロードの分量が目標値よりも大きい場合は、読み取りオペレーションを効率化して、暗号化のオーバーヘッドを小さくします。 接続を最適化する
データ構造を最適化する
クエリベースのルールを使用してダウンロードを制限する
SSL セッションを再利用する
リスナーを効率化する
データへのアクセスを制限する
ストレージ 使用されてないデータが保存されていないか確認します。また、保存するデータを他のデータベースまたは Firebase サービスに分散させて、割り当てを超えないようにします。 使用されていないデータをクリーンアップする
データ構造を最適化する
データベース間でデータをシャーディングする
Cloud Storage for Firebase を使用する

接続を最適化する

GETPUT などの RESTful リクエストは接続を要求します。たとえ接続時間が短い場合であっても、接続が発生することに変わりはありません。このような短時間の接続が頻繁に行われた場合、データベースに対するリアルタイムのアクティブな接続と比較すると、接続コスト、データベースの負荷、送信帯域幅が大幅に増大することがあります。

可能な限り、REST API ではなく、アプリのプラットフォームに対応したネイティブ SDK を使用してください。ネイティブ SDK を使用すると、開いている接続が維持されるため、REST API を使用した場合よりも SSL 暗号化コストやデータベースの負荷が削減されます。

REST API を使用する場合は、HTTP keep-alive を使用して開いている接続を維持するか、またはサーバー送信イベントを使用して SSL handshake によるコストを削減するようにしてください。

複数のデータベース間でデータをシャーディングする

データを複数の Realtime Database インスタンスに分割する方法(データベース シャーディング)には、次の 3 つのメリットがあります。

  1. データベース インスタンス間で接続を分割することにより、アプリで許可されるアクティブな同時接続の総数を増やすことができます。
  2. データベース インスタンス間で負荷を分散できます。
  3. 独立したデータセットにのみアクセスする必要がある独立したユーザー グループがある場合に、異なるデータベース インスタンスを使用して、高いスループットと低いレイテンシを実現できます。

Blaze の料金プランを使用している場合は、1 つの Firebase プロジェクト内で複数のデータベース インスタンスを作成して、データベース インスタンス間で共通のユーザー認証方式を利用できます。

どのような場合にデータのシャーディングを行うか、およびその方法をご覧ください。

効率的なデータ構造を構築する

Realtime Database は、目的のパスだけでなく、そのパスの子ノードからもデータを取得するため、データ構造をできるだけフラットに維持するのが合理的です。データ構造をフラットにすると、必要なデータを選択的に取り出すことができ、不要なデータをクライアントにダウンロードすることもなくなります。

データを構造化する場合は、特に書き込みと削除について考慮してください。たとえば、リーフ数が数千になるパスは削除するのにコストがかかる可能性があります。これらのパスを複数のパスに分割して複数のサブツリーを構成し、ノードあたりのリーフ数を減らすと、削除時間を短縮できます。

また、書き込みを行うたびに、データベース全体の利用率が 0.1% 消費されます。SDK 内の update() メソッドまたは RESTful PATCH リクエストを使用してマルチパスを更新するときに、複数の書き込みを 1 回のオペレーションで一括処理できるようにデータを構造化してください。

データ構造を最適化してパフォーマンスを向上させるには、データ構造のベスト プラクティスに従ってください。

不正アクセスを防止する

Realtime Database Security Rules を使用して、データベースに対する不正オペレーションを防止します。たとえば、ルールを使用することによって、悪意のあるユーザーがデータベース全体を繰り返しダウンロードする行為を防止できます。

Firebase Realtime Database ルールの使用をご覧ください。

クエリベースのルールを使用してダウンロードを制限する

Realtime Database Security Rules は、データベース内のデータへのアクセスを制限します。また、読み取りオペレーションで返されるデータを制限する機能としても利用できます。query. 式(query.limitToFirst など)で定義したクエリベースのルールを使用すると、クエリはルールによって制限されたデータのみを取得するようになります。

たとえば次のルールでは、読み取りアクセスの対象を、優先度順に並べ替えられた最初の 1,000 件のクエリ結果のみに制限します。

messages: {
  ".read": "query.orderByKey &&
            query.limitToFirst <= 1000"
}

// Example query:
db.ref("messages").limitToFirst(1000)
                  .orderByKey("value")

詳細については、Realtime Database Security Rules についてをご覧ください。

クエリでインデックスを使用する

データのインデックスを作成すると、アプリで実行される各クエリの合計使用帯域幅が減ります。

SSL セッションを再利用する

TLS セッション チケットを発行して、接続再開時の SSL 暗号化オーバーヘッド コストを削減します。これは、データベースに対してセキュアな接続を頻繁に行う必要がある場合に特に役立ちます。

リスナーを効率化する

リスナーをできるだけ経路の下流に配置して、同期されるデータの量を制限します。リスナーは、取得するデータの近くに配置する必要があります。データベースのルートではリッスンしないでください。データベース全体がダウンロードされてしまいます。

クエリを追加してリッスン オペレーションで返されるデータを制限し、データの更新のみをダウンロードするリスナーを使用します。たとえば、once() でなく、on() を使用します。.once() は、データの更新が不要なアクションのために確保しておいてください。また、最高のパフォーマンスが得られるように、可能な限り orderByKey() を使用してクエリを並べ替えてください。orderByChild() で並べ替えると、処理時間が 6~8 倍かかることがあります。orderByValue() で並べ替えると、永続的なレイヤから場所全体を読み取る必要が生じるため、データセットが大きい場合に処理速度が大幅に低下することがあります。

リスナーを動的に追加し、不要になったら削除するようにしてください。

使用されていないデータをクリーンアップする

データベース内の使用されていないデータまたは重複データを定期的に削除します。backups を実行すると、データを手動で検査したり、Google Cloud Storage バケットに定期的にバックアップしたりできます。保存対象のデータを Cloud Storage for Firebase を使用してホストすることも検討してください。

更新できるスケーラブルなコードを提供する

IoT デバイスに組み込まれるアプリには、簡単に更新できるスケーラブルなコードを使用する必要があります。ユースケースを完全にテストし、ユーザー数が激増する可能性がある場合にも対応できるようにして、コードの更新をデプロイする機能を組み込むようにしてください。データのシャーディングなどを行う場合は、今後必要となる可能性がある主要な変更点について慎重に検討してください。