🤔

結局RDBよりもFirestoreを使うべきシーンとはどういうときなんだ

2024/12/14に公開

Firestoreをチームでの知見を得る目的でデータベースとして導入しました。
その目的自体の良し悪しは一旦脇に置くとして、ある程度の知見を得ることができた一方で、Firestoreを深く考えずに導入した結果、開発が難しくなった場面もありました。
時には「RDBのほうが良かったのでは」と思うことも 🤔

もちろん、FirestoreとRDB(他にも選択肢がありますが)の良し悪しや選定基準は、様々な側面から検討すべきものであり、単純に比較するのは難しいです。
しかし、データベースの根本的な機能である「データの保存と出力」に立ち返り、「どのようなデータを、どう扱いたいのか」という視点で考えることが、最も重要だと個人的には感じました。

本記事では、上記の観点からFirestoreを使うべきシーンの一つを共有したいと思います。

結論

  • 「どのようなデータを、どう扱いたいのか」という視点で、補完的に使い分けれるならそれが良い
  • 大前提、表形式で表現できるような構造化データを扱うならRDBが良い
  • 半構造化・非構造化データを扱うならFirestoreのようなNoSQLデータベースが良い

安易にFirestoreを導入して大変だったこと

RDBの扱いや思考には比較的慣れているものの、NoSQL・Firestore自体への理解が浅かったことで、コレクション設計や実際の開発においてはその違いや特徴を理解して開発するのが大変でした。
完全に導入する際の認識の甘さによるものですね。
たとえば以下の点です。

1. 結合ができない

FirestoreではRDBのような結合(JOIN)がサポートされていないため、そもそも正規化設計に不向きです。
なので複数のコレクションの関連性をもって扱いたいデータは、一度取得した後に結合するクライアントサイドジョインを行うか、そもそも複数のコレクションで同じデータを重複して持つような設計が必要になります。
これは設計の時点でその特性を理解しコレクションを設計すれば、ある程度は問題ないですが、どうしてもデータの読み込みや書き込み数が無駄に多くなってしまうこともあり、コストの面におていもRDBの方が良いのではと感じられるところでした。

2. 検索機能の制約

  • LIKE検索が非対応。
  • !=inクエリに制限があり、複数条件の処理が複雑化する。
  • 外部ツール(例: Elasticsearch)での拡張は可能だがコストがかかる。

他にも色々RDBを前提として考えていると設計〜開発の時点で難しく感じる部分は多いです。
ただ、そもそもなぜこんなにもRDBの方が良いのではないかと感じられていたのかというと、

  • 表形式で扱えるデータをFirestoreでやろうとしていた

もうこれに尽きます。

RDBでも不自由なく扱えるような表形式をイメージしてデータを格納していたので、じゃあRDBでいいじゃないかということです。

もちろんFirestoreでもそのような構造化データを扱うことはできますし、それ自体が全て誤った使い方だということはないと思います。

ただ、Firestoreはそもそも「半構造化データ」を扱いやすいよというデータベースなので、そこで構造化データを扱おうと思うと、既述の結合での不便さなどがおもむろに現れます。

考えれば当たり前のことでしかないのですが、どういう形で保存したいのか、それをどんな形で加工・出力したいのかということに立ち返ってデータベースを選定する重要さを実感しました。

とはいえ、開発をしていて Firestoreが適していたなというシーンもありました。それが、半構造化データとしてデータを扱いたい場面です。

半構造化データをFirestoreで扱う

具体例: HTMLフォームデータの管理

たとえば、サイトのHTMLフォームを取得して、各サイトが持っているすべての入力フィールドを保存し、それぞれの入力フィールドが何のフィールドなのかを特定したいということがありました。

  1. フォーム1
<form action="submit">
  <input name="user_氏名" type="text" />
  <input title="メールアドレス" type="email" />
  <input name="user_電話番号" type="tel" />
</form>
  1. フォーム2
<form action="submit">
  <input name="user_family" type="text" />
  <input name="user_name" type="text" />
  <input name="user_company" type="text" />
  <input title="メールアドレス" type="email" />
</form>

このような場合、サイトによってフィールドの数や種類が違ってくるので、スキーマを統一できません。
まさに表形式のような形で構造化できない例でした。

Firestoreへの格納例

HtmlData (コレクション)
  └─ docId123 (ドキュメント)
       ├─ url: "https://example.com/form1"
       ├─ fullName: "input[name*='氏名']"
       ├─ email: "input[title*='メール']"
       └─ tel: "input[name*='電話']"

  └─ docId124 (ドキュメント)
       ├─ url: "https://example.com/form2"
       ├─ familyName: "input[name*='family']"
       ├─ lastName: "input[name*='name']"
       ├─ companyName: "input[name*='company']"
       └─ email: "input[title*='メール']"

このような、HTMLという半構造化データをそのまま半構造化データとして保存して扱いたい場面では、Firestoreのスキーマレスという特性を生かすことができるとても良い例だったと思います。

また、他にもスキーマレスという側面においては、比較的フロントエンド部分やUIの要求に応じたデータ設計がしやすいので、そういう前提で考えればある意味直感的で効率的なDB設計をすることもできるなとは感じました。

まとめ

Firestoreを使うべきか、それともRDBを使うべきか(もちろん他の選択肢も含め)は、扱うデータが構造化データなのか、それとも非構造・半構造データなのかという違いが大きな判断基準になると感じました。

  • 構造化データの場合: RDBが最適。
  • 非構造・半構造データの場合: FirestoreなどのNoSQLが適している。

いろんな意見を聞いてみたいです🤔

Discussion