cloud firestoreの概念とSQLとの違い、特徴を知る。

# cloud firestoreの概念とSQLとの違い、特徴を知る。
個人開発でIot AIを利用したシステムを制作するにあたって、GCPのIot CoreとPub/Sub、Cloudfunctionを使用した簡単な仕組みをすでに構築していたので連携がしやすそうだったのと、開発の工数の削減を目的としてバックエンドにfirebaseを利用することを検討していました。
そのなかでfirebaseの提供しているデータベースであるCloud Firestoreをデータベースとして利用するべきか否かを判断するため、リレーショナルデータベースとの主な違いやCloud Firestoreも特徴をまとめてみました。

## cloudfirestoreとは
firebseで提供されるサービスで推奨されるメインのデータベースサービス

サービスとして提供される内容特徴
- クライアントのsdk
- 一定の範囲内の無料枠と従量課金
- リアルタイムのアップデート

cloudfirestoreはデータをドキュメントのコレクションとして保存する(ドキュメント指向データベース)。
## 特徴
JSONと似た形式で保存する。
複雑で階層的なデータはサブコレクションとして使用することで簡単に扱うことができる

### SQLとのちがい

**SQLについて**
一般的にビジネスデータ処理で広く使われるリレーショナルデータベースでは、
実世界を表現するために、全てのデータをテーブル(表)で表現しわかりやすくしているという特徴があり、数学の集合論に基づいた徹底的にフォーマルなデータモデル(リレーショナルデータモデル)を採用したデータベースである。

データ定義やデータ操作などの機能を有するデータベース言語として、
国際標準リレーショナルデータベース言語であるSQLを使用している。
*ISO ANSIなどの取り組みで 1987年に制定され、幾度となく改正されている。
<br>
→リレーショナルデータベースは、
実世界データ化する時にを表に落とし込んでわかりやすくしている
「リレーショナルデータモデル」を採用したデータベースで、
<font color="Red">
データベースの操作のためにSQLという言語を使っている
</font>
リレーショナルデータベースでは業務データを正確に扱うことを重要視していて、トランザクション保証・スキーマ・参照完全性に力を注いで開発されてきた。

参考：増永良文. データベース入門[第2版]. サイエンス社,2021


### NoSQLについて

モバイルアプリ等の普及やSNSの流行、センサからのデータの扱いや位置データなど大量で多種類のデータ(ビッグデータ)の扱いで、これまでの管理するデータをあらかじめ決めて、構造に合わせたデータ管理をするリレーショナルデータベースの枠組みでは扱いづらく、変化に柔軟に対応できる変化に強い構造をとるNoSQLの技術が開発されてきた。
ビッグデータの扱いでは
大量(Volume)で多様(Variety)なデータを高速に処理(velocity)することが求められてきており、NoSQLはそのようなニーズに適したデータベースとして利用されている。

NoSQLのサーバは大量の安価なサーバを繋げて並列に処理を行うスケールアウトによってパフォーマンスを向上させる手法をとっており、大量のデータを高速に処理することができるようになっているのに対して、そのデメリットとして全体のデータの整合性を担保する側面に弱いという点が挙げられる(特にデータの一貫性を保つのが弱い)。


- リレーショナルデータベース以外のSQLを使用しないデータベースの総称をNoSQLと呼び、その種類は
- キー・バリュー型
- 列指向型
- ドキュメント指向型
- グラフデータベース
などさまざま

参考
- https://www.youtube.com/watch?v=4M4bh_sdT48
- https://www.kaonavi.jp/dictionary/big-data/


## データモデル
https://firebase.google.com/docs/firestore/data-model?hl=ja

cloud firestoreもまたNoSQLのドキュメント指向型のデータベースである。
ほとんどJSONを扱うような形でドキュメント指向型データモデルはキーバリュー形式の階層構造をとる。

データは「ドキュメント」に格納され「コレクション」にまとめられる。


（イメージ）
コレクション
┃
┣ ドキュメント1
┃	┣ キー１━バリュー１
┃	┣ キー２━バリュー２
┃
┣ ドキュメント2
┃	┣ キー１━バリュー１
┃	┣ キー２━バリュー２
┃
┗ ドキュメント３
 　  ┣サブコレクション１
　   　┣ キー１━バリュー１
  　 　┣ キー２━バリュー２



**特徴**
- ドキュメント単位でキーバリューの一連データを保持する。
- 複雑なデータを場合にネストされたドキュメントによってデータを保持する（サブコレクション）
- サブコレクションのネストは最大１００回
- ドキュメント内のサブコレクションドキュメントを削除するだけではデータベース内で削除されず保持されたままになりさんしょうできるままになってしまう。
- スキーマレスで柔軟にデータを保持できる。
など

webアプリケーションの開発において取得したいデータ構造と近い構造をとっていて、
階層ごとに必要最低限のドキュメント単位でデータを取得することが可能で
オーバーフェッチが少なくすむことや、プログラムでも扱いやすい形でデータを取得することができるのが利点？🤔
また、リレーショナルデータベースにおいてビジネス側の要求の変更に応じてデータ構造の変更が必要になった場合、スキーマの変更も必要になってしまい、仕様の変更が難しかった問題も解決できる。

**firestoreデータ設計のポイント**
- jsonのような階層構造でデータを保持しているためコレクション間のドキュメント同士のリレーションを持たせる場合、階層のパスまで含めて保存したドキュメントリファレンスを保持する。
  - https://speakerdeck.com/1amageek/firestore-database-design?slide=19
  - https://zenn.dev/sukedon/scraps/356694a8a1cc8d


- 従来サーバ側で行っていたデータの取得と結合の結果としてのjsonの返却を行わず、クライアントサイドでドキュメントリファレンスを参照してデータの結合を行う<br>→クライアントサイドジョイン。
  - https://speakerdeck.com/1amageek/firestore-database-design?slide=16
  - https://qiita.com/1amageek/items/afc1c0ceb15ffc2372fd



- 非正規化を許容してリード数を減らしたりすることで高速な処理やリアルタイム性を求めることも推奨されている。非正規化かドキュメントリファレンスによるクライアントサイドジョイン、ケースによってにって適した構成でデータのモデリングを行う
  - https://zenn.dev/t0_inoue/articles/bb3b177f77412e
  - https://zenn.dev/mamushi/scraps/1b9c31666ee264




サポートされているデータ型
https://firebase.google.com/docs/firestore/manage-data/data-types?hl=ja

*ドキュメント内でネストされたオブジェクトはマップと呼ばれる。
*キーバリュー単位をフィールドと呼ぶ


## インデックスについて

データベース内のマップやフィールドに対して
Cloud firestoreにはインデックス管理にかかる時間を短縮するために自動インデックスがなされていて、インデックスをもとにクエリ操作を行うことになる。
自動インデックス以外にもアプリで必要なインデックスを追加することも可能。



### 単一フィールドインデックス
特定の一つのフィールド、およびマップごとに対してfirestoreの自動インデックス機能で保持されるインデックス。

> 配列でもなくマップでもないフィールドに対しては、コレクションのスコープを使用する 2 つの単一フィールド インデックス（1 つは昇順モード、1 つは降順モード）が定義されます。
マップ フィールドに対しては、マップ内の配列ではない、およびマップではない各サブフィールドごとに、コレクションのスコープを使用する 1 つの昇順インデックスと 1 つの降順インデックスが作成されます。
ドキュメント内の配列フィールドに対しては、コレクションのスコープ配列の内容インデックスが作成、維持されます。
コレクション グループのスコープがある単一フィールド インデックスは、デフォルトでは維持されません。

引用：https://firebase.google.com/docs/firestore/query-data/index-overview?hl=ja#automatic_indexing

単一フィールドインデックスを除外することも可能

### 複合インデックス
https://firebase.google.com/docs/firestore/query-data/index-overview?hl=ja#composite_indexes

単一フィールドによるインデックスでは実現できないクエリを複数のフィールドに対してインデックスを貼ることで実現する。
インデックスを作成する時にそれぞれインデックスモード([昇順、降順、配列の内容])をいずれか選択し、選択した内容のクエリがインデックスに対して利用することができるようになる。

複合インデックスによって一回のクエリで複数のフィールドで同時にwhereやorderby、配列によるwhere検索ができるようになる？🤔

参考：https://yamatooo.blog/entry/2021/01/19/083000


## まとめ
ここまでまとめてみて今回個人開発でやりたいことの実現においてfirestoreを実際に利用することにしました。
データの設計において悩んだことが
- 実体関連モデルからドキュメント指向型データモデルに落とし込む手法
- 非正規化をどこまで許容するべきか
- firestoreの料金を抑えるための設計

これらについて確立された手法やネット上での情報が比較的少なかったかなという印象でデータ設計に少し手こずりました。。。

firestoreのみならずfirebaseのさまざまな機能はフルマネージドでインフラのことを考えずともサービスの開発ができるという点や、サーバダウンや利用者が少ない個人開発やスモールスタートの事業等ではとても優秀なものだと思いましたが、一方で使い方を誤ったり、設計のミスで利用コストが増えたり、外部からの攻撃等で大量のリクエストが飛んだりなどすると料金が無限にかかるのが怖いとも思いました。

が、firebase自体とても便利でfirebaseCLIとフロントエンドの開発で簡単にリクエストベースで料金が発生するREST APIの自作とホスティングができて非常に魅力的で今後も案件や個人開発での利用、ネットでの発信もしていけたらなと思ってます。


### 参考文献

増永良文. データベース入門[第2版]. サイエンス社,2021
https://www.amazon.co.jp/%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-Computer-Science-Library/dp/4781915000/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=A3YO3RTNV5N5&keywords=%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E5%85%A5%E9%96%80&qid=1660418996&sprefix=%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E5%85%A5%E9%96%80%2Caps%2C344&sr=8-1