コンソールへ移動

複数のデータベースでスケールする

Firebase Realtime Database でパフォーマンスを最適化し、データをスケーリングする最善の方法は、データを複数の Realtime Database インスタンスに分割すること(データベース シャーディング)です。シャーディングを行うと、負荷分散やパフォーマンスの最適化だけでなく、個々のデータベース インスタンスに適用される制限を超えてスケーリングできる柔軟性が得られます。

データをシャーディングするタイミング

以下のいずれかのシナリオで Realtime Database を使用している場合は、複数のデータベースにデータをシャーディングすることをおすすめします。

  • 単一のデータベース インスタンスに適用される同時接続数 100,000、1 秒あたり 1,000 回の書き込みオペレーション、またはその他の制限を超えてスケーリングする場合。
  • 独立した複数のデータセットがあり、パフォーマンスを最適化する必要がある場合(たとえば、個別の独立したユーザー グループにサービスを提供するチャットアプリ)。
  • 複数のデータベース間で負荷を分散して稼働率を向上させ、単一のデータベース インスタンスの過負荷リスクを軽減する場合。

データをシャーディングする方法

データをシャーディングする手順は次のとおりです(詳細は後述します)。

  1. アプリ固有のニーズに応じて、複数のデータベースにデータをマッピングします。
  2. 複数のデータベース インスタンスを作成します。
  3. データセットごとに必要な Realtime Database インスタンスに接続するようにアプリを構成します。

データをマッピングする

データを複数のデータベースにマッピングする場合は、以下の条件を満たすようにしてください。

  • 各クエリが、単一のデータベース インスタンスに対してのみ実行されること。Realtime Database では、複数のデータベース インスタンスに対するクエリはサポートされていません。
  • 複数のデータベース インスタンス間でデータの共有や重複が発生しないこと(または共有や重複を最小限に抑えること)。
  • ある時点で、各アプリ インスタンスが 1 つのデータベースだけに接続すること。

データをマッピングする際には、次の戦略を使うことをおすすめします。

「マスター シャード」を作成する

データが複数のデータベース インスタンス間にどのように格納されているかを示すマップを保存します。これにより、接続するクライアントに対応するデータベース インスタンスをプログラムによって検索できます。ただし、特定のデータベース インスタンスを必要とする場合は、直接接続するよりもオーバーヘッドが増える可能性があることに注意してください。

カテゴリ別またはお客様別のバケットデータ

ユーザータイプまたはデータ型でデータベース インスタンスをサイロ化してデータを保存します。たとえば、複数の組織にサービスを提供するチャットアプリを構築する場合は、組織ごとにデータベース インスタンスを作成し、すべてのチャットデータを固有のデータベース インスタンスに格納できます。

この場合、組織 A と組織 B はデータを共有せず、データベース内に重複データは発生せず、単一のデータベース インスタンスに対してのみクエリが実行されます。さらに、各組織のユーザーがチャットアプリを使用するときは、各自の組織のデータベースだけに接続します。

この場合、あらかじめ複数のデータベース インスタンスを作成しておき、組織の ID を使用して、そのデータベース インスタンスにチームをマッピングできます。たとえば、組織 A を Realtime Database A にマッピングします。

アプリのデータをマッピングする方法は、各自のユースケースによって異なりますが、前述の条件は、データに適した定義を行うのに役立ちます。

複数の Realtime Database インスタンスを作成する

Blaze お支払いプランをご利用の場合は、同じ Firebase プロジェクト内に複数のデータベース インスタンスを作成できます。

データベース セクションのコンテキスト メニューを使用して Firebase コンソールにデータベースを作成する

  1. Firebase コンソールで、[開発] > [Database] セクションの [データ] タブに移動します。
  2. [Database] セクションのメニューから [新しいデータベースを作成] を選択します。
  3. データベース参照セキュリティ ルールをカスタマイズして、[OK] をクリックします。

このプロセスを繰り返して、必要なだけデータベース インスタンスを作成します。各データベース インスタンスには独自の Firebase Realtime Database ルールセットがあり、データへのアクセスを微調整できます。

各インスタンスの Realtime Database ルールの編集とデプロイ

Realtime Database ルールにより、プロジェクト内の各データベース インスタンスへの適切なアクセスが許可されていることを確認します。各データベースには独自のルールセットがあり、ルールの編集やデプロイは Firebase コンソールから行います。また、デプロイ ターゲットに対する Firebase CLI を使用してルールの編集やデプロイを行うこともできます。

  • Firebase コンソールからルールを編集してデプロイする手順は次のとおりです。

    1. [開発] > [Database] セクションの [ルール] タブに移動します。
    2. 編集するデータベースを選択し、ルールを変更します。
  • Firebase CLI からルールを編集してデプロイする手順は次のとおりです。

    1. データベース インスタンスのルールファイル(foo.rules.json など)でルールを変更します。
    2. デプロイ ターゲットを作成してデプロイし、同じルールファイルを使用するデータベースを関連付けます。例:
      firebase target:apply database main my-db-1 my-db-2
      firebase target:apply database other my-other-db-3
    3. デプロイ ターゲットを使用して firebase.json 構成ファイルを更新します。

      {
        "database": [
          {"target": "main", "rules", "foo.rules.json"},
          {"target": "other", "rules": "bar.rules.json"}
        ]
      }
      
    4. deploy コマンドを実行します。

      firebase deploy

常に同じ場所からルールを編集してデプロイするようにしてください。Firebase CLI からルールをデプロイすると、Firebase コンソールで行った編集がオーバーライドされ、Firebase コンソールで直接ルールを編集すると、Firebase CLI でデプロイした最新の変更がオーバーライドされます。

アプリを複数のデータベース インスタンスに接続する

セカンダリ データベース インスタンスに保存されているデータにアクセスするには、データベース参照を使用します。特定のデータベース インスタンスの参照は URL またはアプリで取得できます。URL を指定しないと、アプリのデフォルト データベース インスタンスの参照が取得されます。

ウェブ
// init
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 database1 = firebase.database(app2);
Swift
// Get the default database instance for an app
var ref: DatabaseReference!
ref = Database.database().reference()
// Get a secondary database instance by 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];
// Get a secondary database instance by URL @property (strong, nonatomic) FIRDatabaseReference *ref; self.ref = [[FIRDatabase databaseWithURL:@"https://testapp-1234.firebaseio.com"] reference];

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

// Get the default database instance for an app
val primary = FirebaseDatabase.getInstance().reference

// Get a secondary database instance by URL
val secondary = FirebaseDatabase
        .getInstance("https://testapp-1234.firebaseio.com").reference

Firebase CLI を使用する場合のインスタンスの指定

Firebase CLI コマンドを適用する Firebase Realtime Database を指定するには、--instance オプションを使用します。たとえば、my-example-shard.firebaseio.com というデータベース インスタンスのプロファイラを実行するには、次のコマンドを使用します。

firebase database:profile --instance "my-example-shard"

各データベースの接続を最適化する

セッション中に各クライアントが複数のデータベースに接続する必要がある場合は、必要なときだけ各データベース インスタンスに接続することで、同時接続数を減らすことができます。

アドバイスが必要な場合

複数のデータベース インスタンスにわたってデータをシャーディングする処理の詳細については、Slack チャンネルStack Overflow から Firebase のエキスパートにお問い合わせください。