firebase
データの構造化
サーチ…
前書き
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に似たクエリが必要とされるほとんどのシナリオでは、データを反転して双方向関係を作成するのが一般的です。
上記のデータベースを使用するアプリケーションで、次のことが必要なアプリケーションを考えてみましょう。
- 特定の学生が取っているコースの一覧を表示して ...
- 特定のコースのすべての生徒をリストする
データベース構造が一方向であった場合、上の2つの要件の1つをスキャンまたは照会するのが非常に遅くなります。いくつかのシナリオでは、冗長性により、頻繁な操作がより迅速かつ効率的になり、長期的には複製のコストは無視できる程度になります。