サーチ…


前書き

Firebaseデータベースは、データを階層JSONオブジェクトの形式で格納するNoSQLデータベースです。 SQLデータベースが通常持っているように、フォームのテーブルやレコードはありません。キー値構造を構成するノードだけです。

データ正規化

適切に設計されたデータベース構造を持たせるためには、データ要件を徹底的に概説し、事前に考慮する必要があります。この場合の構造は正規化する必要があります。 JSONツリーがフラットであればあるほど、データアクセスが高速になります。

べし・べからず集

間違ったやり方

次の構造を考えてみましょう

{
  "users": {

    // Uniquely generated IDs for children is common practice,
    // it's actually really useful for automating child creation.
    // Auto-incrementing an integer for a key can be problematic when a child is removed.

    "-KH3Cx0KFvSQELIYZezv": {     
      "name": "Jon Snow",
      "aboutMe": "I know nothing...",
      "posts": {
        "post1": { 
          "body": "Different roads sometimes leads to the same castle", 
          "isHidden": false
        },
        "post2": { ... },
        // Possibly more posts
      }
    },
    "-KH3Dx2KFdSLErIYZcgk": { ... },     // Another user
    // A lot more users here
  }
}

これはやってはいけないことの素晴らしい例です。上記のような複数のネストされた構造は非常に問題があり、大きなパフォーマンス低下を引き起こす可能性があります。

Firebaseがノードにアクセスする方法は、すべての子のデータをダウンロードしてから、すべての同じレベルのノード(すべての親の子)を反復することです。さて、数百(または数千)の投稿を持つ複数のユーザを持つデータベースを想像してみましょう。この場合のポストへのアクセスは、数百メガバイトの未使用データを潜在的にロードする可能性があります。より複雑なアプリケーションでは、ネストは4つのレイヤーよりも深くなり、無駄なダウンロードと繰り返しが発生します。

正しい道

同じ構造を平坦化すると、次のようになります

{
  // "users" should not contain any of the posts' data
  "users": {
    "-KH3Cx0KFvSQELIYZezv": {
      "name": "Jon Snow",
      "aboutMe": "I know nothing..."
    },
    "-KH3Dx2KFdSLErIYZcgk": { ... },
    // More users
  },

  // Posts can be accessed provided a user key
  "posts": {
    "-KH3Cx0KFvSQELIYZezv": {     // Jon Snow's posts
      "post1": { 
        "body": "Different roads sometimes leads to the same castle", 
        "isHidden": false
      },
      "post2": { ... },
      // Possibly more posts
    },
    "-KH3Dx2KFdSLErIYZcgk": { ... },
    // other users' posts
  }
}

これは、対象オブジェクトにアクセスするために必要なノード数を減らし、オーバーヘッドを大幅に削減します。投稿を持たないすべてのユーザー投稿ブランチに存在しないので、上記の間違った方法でそれらのユーザーを繰り返し処理することは全く役に立たない。

双方向の関係

以下は、双方向関係を使用するシンプルで最小限のカレッジデータベースの例です

{
  "students": {
    "-SL3Cs0KFvDMQLIYZEzv": {
      "name": "Godric Gryffindor",
      "id": "900130309",
      "courses": {
         "potions": true,
         "charms": true,
         "transfiguration": true, 
      }
    },
    "-SL3ws2KvZQLTYMqzSas": {          
      "name": "Salazar Slytherin",
      "id": "900132319",
      "courses": {
         "potions": true,
         "herbs": true,
         "muggleStudies": true, 
      }
    },
    "-SL3ns2OtARSTUMywqWt": { ... },
    // More students here
  },

  "courses": {
    "potions": {
      "code": "CHEM305",
      "enrolledStudents": {
        "-SL3Cs0KFvDMQLIYZEzv": true,     // Godric Gryffindor
        "-SL3ws2KvZQLTYMqzSas": true,     // Salazar Slytherin
        // More students
      }
    },
    "muggleStuddies": {
      "code": "SOC215",
      "enrolledStudents": {
        "-SL3ws2KvZQLTYMqzSas": true,     // Salazar Slytherin
        "-SL3ns2OtARSTUMywqWt": true,     // Some other student
        // More students
      }
    },
    // More courses
  }
}

各受講者にはコースリストがあり、各コースには受講生のリストがあります

冗長性は常に悪いアプローチではありません。ストレージ・スペースを必要とし、複製されたノードを削除または編集するときに複数のエントリーの更新を処理しなければならないことは事実です。ただし、データが頻繁に更新されないシナリオでは、双方向の関係を持つことでフェッチ/書き込みプロセスが大幅に緩和される可能性があります。

SQLに似たクエリが必要とされるほとんどのシナリオでは、データを反転して双方向関係を作成するのが一般的です。

上記のデータベースを使用するアプリケーションで、次のことが必要なアプリケーションを考えてみましょう。

  1. 特定の学生が取っているコースの一覧を表示して ...
  2. 特定のコースのすべての生徒をリストする

データベース構造が一方向であった場合、上の2つの要件の1つをスキャンまたは照会するのが非常に遅くなります。いくつかのシナリオでは、冗長性により、頻繁な操作がより迅速かつ効率的になり、長期的には複製のコストは無視できる程度になります。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow