Firebase Realtime Database でパフォーマンスを最適化し、データをスケーリングする最善の方法は、データベース シャーディングとも呼ばれる複数の Realtime Database インスタンスにデータを分割することです。シャーディングにより、負荷分散とパフォーマンスの最適化に加えて、個々のデータベース インスタンスに適用される制限を超えて柔軟にスケーリングできます。
データをいつシャーディングするか
Realtime Database を使用していて、次のいずれかのシナリオに当てはまる場合は、複数のデータベースにまたがってデータを分割することをお勧めします。
- 200,000 の同時接続の制限、1,000 の書き込み操作/秒、または単一のデータベース インスタンスのその他の制限のいずれかを超えてスケーリングする必要があります。
- 複数の個別のデータ セットがあり、パフォーマンスを最適化したい場合 (たとえば、個別の独立したユーザー グループにサービスを提供するチャット アプリ)。
- アップタイムを改善し、単一のデータベース インスタンスが過負荷になるリスクを軽減するために、複数のデータベース間で負荷を分散したいと考えています。
データを分割する方法
データをシャーディングするには、次の手順に従います (以下で詳しく説明します)。
- アプリ固有のニーズに応じて、データを複数のデータベースにマップします。
- 複数のデータベース インスタンスを作成します。
- 各データセットに必要な Realtime Database インスタンスに接続するようにアプリを構成します。
データをマッピングする
データを複数のデータベースにマッピングする場合は、次の条件を満たすようにしてください。
- 各クエリは、1 つのデータベース インスタンスに対してのみ実行されます。 Realtime Database は、データベース インスタンス間のクエリをサポートしていません。
- データベース インスタンス間でデータを共有または複製しない (または最小限の共有または複製)。
- 各アプリ インスタンスは、常に 1 つのデータベースにのみ接続します。
データをマッピングするときは、次の戦略を適用することを検討してください。
「マスターシャード」を作成する
データベース インスタンス間でのデータの保存方法のマップを保存します。このようにして、接続しているクライアントに対応するデータベース インスタンスをプログラムで検索できます。これは、必要なときに必要な特定のデータベース インスタンスに直接接続するよりもオーバーヘッドが大きくなる可能性があることに注意してください。
カテゴリー別または顧客別のバケットデータ
ユーザーまたはデータ型ごとにグループ化された、サイロ化されたデータベース インスタンスにデータを格納します。たとえば、複数の組織にサービスを提供するチャット アプリケーションを構築する場合、組織ごとにデータベース インスタンスを作成し、すべてのチャット データを一意のデータベース インスタンスに格納できます。
この場合、組織 A と組織 B はデータを共有しておらず、データベースに重複データはなく、単一のデータベース インスタンスに対してのみクエリを実行します。さらに、各組織のユーザーは、チャット アプリを使用する場合にのみ組織のデータベースに接続します。
その後、事前にいくつかのデータベース インスタンスを作成し、組織の ID を使用してチームをそのデータベース インスタンスにマップできます。たとえば、組織 A が Realtime Database A にマッピングされているとします。
アプリのデータをマッピングする方法は、特定のユース ケースによって異なりますが、上記で概説した条件と戦略は、データに対して何が機能するかを定義するのに役立ちます。
複数の Realtime Database インスタンスを作成する
Blaze 料金プランをご利用の場合は、同じ Firebase プロジェクトに複数のデータベース インスタンスを作成できます。
- Firebase コンソールで、[開発] > [データベース] セクションの [データ] タブに移動します。
- [ Realtime Database ] セクションのメニューから [ Create new database ] を選択します。
- データベース参照とセキュリティ ルールをカスタマイズし、[了解] をクリックします。
このプロセスを繰り返して、必要な数のデータベース インスタンスを作成します。各データベース インスタンスには独自の Firebase Realtime Database ルール セットがあるため、データへのアクセスを微調整できます。
Firebase コンソールで、またはRealtime Database Management REST APIを使用して、データベース インスタンスを作成および管理できます。
各インスタンスの Realtime Database ルールを編集してデプロイする
Realtime Database ルールで、プロジェクト内の各データベース インスタンスへの適切なアクセスが許可されていることを確認してください。各データベースには独自のルール セットがあり、Firebase コンソールから編集してデプロイするか、 Firebase CLI を使用してターゲットをデプロイできます。
Firebase コンソールからルールを編集してデプロイするには、次の手順に従います。
- [開発] > [データベース] セクションの[ルール] タブに移動します。
- 編集するデータベースを選択し、ルールを変更します。
Firebase CLI からルールを編集してデプロイするには、次の手順に従います。
- データベース インスタンスのルール ファイルのルールを変更します (たとえば、
foo.rules.json
)。 - デプロイ ターゲットを作成して適用し、同じルール ファイルを使用するデータベースを関連付けます。例:
firebase target:apply database main my-db-1 my-db-2
firebase target:apply database other my-other-db-3
デプロイ ターゲットで
firebase.json
構成ファイルを更新します。{ "database": [ {"target": "main", "rules": "foo.rules.json"}, {"target": "other", "rules": "bar.rules.json"} ] }
デプロイ コマンドを実行します:
firebase deploy
- データベース インスタンスのルール ファイルのルールを変更します (たとえば、
常に同じ場所からルールを編集して展開するようにしてください。 Firebase CLI からルールをデプロイすると、Firebase コンソールで行った編集が上書きされ、Firebase コンソールでルールを直接編集すると、Firebase CLI を介してデプロイした最近の変更が上書きされます。
アプリを複数のデータベース インスタンスに接続する
データベース参照を使用して、セカンダリ データベース インスタンスに格納されているデータにアクセスします。 URL またはアプリで特定のデータベース インスタンスの参照を取得できます。 URL を指定しない場合は、アプリの既定のデータベース インスタンスの参照が取得されます。
Web version 9
import { initializeApp } from "firebase/app"; import { getDatabase } from "firebase/database"; const app1 = initializeApp({ databaseURL: "https://testapp-1234-1.firebaseio.com" }); const app2 = initializeApp({ databaseURL: "https://testapp-1234-2.firebaseio.com" }, 'app2'); // Get the default database instance for an app1 const database1 = getDatabase(app1); // Get a database instance for app2 const database2 = getDatabase(app2);
Web version 8
const app1 = firebase.initializeApp({ databaseURL: "https://testapp-1234-1.firebaseio.com" }); const app2 = firebase.initializeApp({ databaseURL: "https://testapp-1234-2.firebaseio.com" }, 'app2'); // Get the default database instance for an app1 var database1 = firebase.database(); // Get a database instance for app2 var database2 = firebase.database(app2);
迅速
// Get the default database instance for an appvar ref: DatabaseReference! ref = Database.database().reference()// URL var ref: DatabaseReference でセカンダリ データベース インスタンスを取得します。 ref = Database.database("https://testapp-1234.firebaseio.com").reference()
Objective-C
// Get the default database instance for an app@property (strong, nonatomic) FIRDatabaseReference *ref; self.ref = [[FIRDatabase database] reference];// URL でセカンダリ データベース インスタンスを取得 @property (強力、非アトミック) FIRDatabaseReference *ref; self.ref = [[FIRDatabase databaseWithURL:@"https://testapp-1234.firebaseio.com"] リファレンス];
Java
// Get the default database instance for an app DatabaseReference primary = FirebaseDatabase.getInstance() .getReference(); // Get a secondary database instance by URL DatabaseReference secondary = FirebaseDatabase.getInstance("https://testapp-1234.firebaseio.com") .getReference();
Kotlin+KTX
// Get the default database instance for an app val primary = Firebase.database.reference // Get a secondary database instance by URL val secondary = Firebase.database("https://testapp-1234.firebaseio.com").reference
Firebase CLI の使用時にインスタンスを指定する
--instance
オプションを使用して、Firebase CLI コマンドを適用する Firebase Realtime Database を指定します。たとえば、次のコマンドを使用して、 my-example-shard.firebaseio.com
という名前のデータベース インスタンスのプロファイラーを実行します。
firebase database:profile --instance "my-example-shard"
各データベースの接続を最適化する
セッション中に各クライアントが複数のデータベースに接続する必要がある場合は、必要な時間だけ各データベース インスタンスに接続することで、各データベース インスタンスへの同時接続数を減らすことができます。
もっとアドバイスをもらう
複数のデータベース インスタンス間でのデータのシャーディングについてさらにサポートが必要な場合は、 Slack チャンネルまたはStack Overflowで Firebase の専門家にお問い合わせください。