比べてみよう リレーショナル vs ドキュメント

[元スライドはこちら](https://www.slideshare.net/MariMurotani/vs-pptx-255045266)

## それぞれの特徴
|| リレーショナルDB(MySQL)| ドキュメントDB(MongoDB)|
|------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| データ構造 | テーブルという表計算ソフトのような構造 正規化という手法を用いて適度に重複が発生しない構造(テーブル)を事前に定義する 正規化は1-3段階まであり厳密な設計思想が存在する | JSON形式 スキーマレスなので事前に全ての定義をする必要はない 緩やかな設計思想で、JSONのモデリングを行う 主キーは自動採番で後からインデックスの設定もできる 遅いけどコレクション結合もできる |
| 処理速度   | インデックスの効率に依存する 細かいメモリチューニングができる HDDに書き込むオーバーヘッドがある                                                                     | インデックスはRDB同様に利用できる インメモリで動くためオーバーヘッドが少なく高速 データの集計などの単純計算はRDBよりも高速にできる                                                         |
| 特性       |[☆ACID特性](https://masawan-guitar.hatenablog.com/entry/2016/08/14/163447#:~:text=%E3%80%90%EF%BC%91%E3%80%91%E3%80%8CRDBMS%E3%80%8D%2D%20ACID%E7%89%B9%E6%80%A7&text=ACID%E7%89%B9%E6%80%A7%E3%81%A8%E3%81%AF%E3%80%81%E3%83%88%E3%83%A9%E3%83%B3%E3%82%B6%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3,%E8%AA%9E%E3%81%A7%E8%A1%A8%E3%81%97%E3%81%9F%E3%82%82%E3%81%AE%E3%80%82)という原則を守る事ができる ※  とても厳格なので金融や基幹システムなどに向いている|[☆Base特性](https://masawan-guitar.hatenablog.com/entry/2016/08/14/163447#:~:text=%E3%80%90%EF%BC%91%E3%80%91%E3%80%8CRDBMS%E3%80%8D%2D%20ACID%E7%89%B9%E6%80%A7&text=ACID%E7%89%B9%E6%80%A7%E3%81%A8%E3%81%AF%E3%80%81%E3%83%88%E3%83%A9%E3%83%B3%E3%82%B6%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3,%E8%AA%9E%E3%81%A7%E8%A1%A8%E3%81%97%E3%81%9F%E3%82%82%E3%81%AE%E3%80%82)という原則を守る事ができる ※ ゲームのセーブデータや粒度の細かい操作ログ記録などに向いている|
| 分散性     | [NDBクラスタ](https://dev.mysql.com/doc/refman/5.6/ja/mysql-cluster.html)という特殊なテーブルを使う以外には基本的にレプリケーションを利用した読み込み分散のみ|シャーディングとい機能を利用して書き込み分散ができる|

## 分散化アーキテクチャ

| 垂直分散 | 水平分散 |
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| MySQL(レプリケーション)| MongoDB(シャーディング) |
|![Screen Shot 2022-12-27 at 8.24.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89997/40038707-b74c-1352-f7ec-bcd14c0435bc.png)|![Screen Shot 2022-12-27 at 8.24.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89997/67ba92eb-dc63-9c53-cbdf-268edd0f8bd1.png)|
| スレーブがマスターのリレーログを読みに行って自分のデータベースに情報を書き込む<br> master ⇐> slave間の整合性を保持するための禁忌事項がいくつかある<br> 日付を指定した削除更新クエリを発行してはいけないなど<br> | shardingしているどのノードにも書き込みができる<br> mongsはキーを元にルーティングをしているだけ<br> 1つのシャードがダウンした場合にデータを転送して別のシャードで復元できる<br> |

※ MongoDBレプリカセットの話は一旦省略しています
くしくは、[こちら](https://www.alibabacloud.com/help/ja/apsaradb-for-mongodb/latest/how-a-replica-set-in-mongodb-works)をご覧ください

## SQL構文の比較
:::note warn
スキーマレスなので、テーブルの設計が不要になり、カラム長の変更や追加削除が用意になる反面、取り出す時の対応をきちんとしないと、null参照によるエラーが発生しやすくなるので注意して利用してください
::::

| MySQL | MongoDB |
|---|---|
| 1. スキーマ定義<br>create table customers ( <br>   id number(10) not null primary key, <br>   name varchar(40) not null,<br>   tell  varchar(40) not null,<br>)<br><br>2. データの投入<br>insert into customers(id, name, tell) values(null, ‘test’, ‘080-0000-0000);’<br><br>3. カラムを増やす<br>alter table customers add address column varchar(255);<br><br>4. データの投入<br>insert into customers(id, name, tell) values(null, ‘test’, ‘080-0000-0000);’ | 1. コレクション定義<br>db.createCollection( "customers")<br><br>2. データを入れる<br>db.customers.insert([{name: ‘test’, tell: ‘080-0000-0000’}])<br><br>3. カラムを増やしてデータを入れる<br>db.customers.insert([{name: ‘test’, tell: ‘080-0000-0000’,address:’Tokyo’}])<br><br><br><br><br><br><br><br><br> |

## 利用例
| MySQL | MongoDB |
|---|---|
| □ECサイトなどの商品管理<br>重複なく設計されたマスタ系のデータテーブルを保管して参照する<br>□銀行システム<br>厳格なトランザクションの下で、入金、出金、振り込みなどの操作を行わなければならない | □大量のログ保管<br>ヒートマップデータやアプリ操作ログなどの保管や統計的集計<br>□ゲームのセーブデータ<br>特定個人のプレイデータで厳密排他制御の必要性がない |

# Railsを利用しないアーキテクチャ例(MongoDB)
| マイクロサービスで情報の蓄積 | 閲覧にはクライアントツールを使う |
|---|---|
| ☆例: 視聴ログなどの蓄積にマイクロサービスを利用する<br>■AWS<br>[MongoDB Atlas serverless architecture](https://docs.aws.amazon.com/prescriptive-guidance/latest/migration-mongodb-atlas/serverless.html)<br>Awsを利用したマイクロサービスのアーキテクチャ<br><br>■Atlas<br>[Microservices with MongoDB Atlas](https://www.mongodb.com/databases/what-are-microservices)<br>MongoDBの提供するマネージドサービス | ☆例: 蓄積されたデータの閲覧ツールを実装せずに閲覧する<br>■ Studio<br>[Studio 3T(GUI client)](https://studio3t.com/?utm_source=Guru99&utm_medium=listing&utm_campaign=leadgen)<br>MySQLだとnavicatというツールがあるがそれと同じもので<br>クエリさえ分かればデータが引き出せるというもの<br>■HumongouS.io<br>[HumongouS.io(Web GUI )](https://www.humongous.io/)<br>上記のWeb版<br><br> |

# 積極的に活用していきたい新機能
## ジオコーディング
| MySQL | MongoDB |
|---|---|
| MySQLにも空間データを扱う型が存在します、PointやPolygonなどの複雑なGeometoryもサポートしています<br>[空間データ型](https://dev.mysql.com/doc/refman/8.0/ja/spatial-type-overview.html)<br>[緯度経度](https://dev.mysql.com/doc/refman/8.0/ja/opengis-geometry-model.html) | MongoDBでは、複雑なGeometry(点、直線、多角形)をlon/latで扱うものと、2Dの座標空間を扱えます(点、四角、多角形、円、Sphere)<br>球面空間でのクエリもサポートしています<br>[Geospatial Queries](https://www.mongodb.com/docs/manual/geospatial-queries/)<br>|

:::note info
どちらも、緯度経度による空間データを扱えるので、近隣の施設などを検索することができます
:::

## グラフ表現

| MySQL(MariaDB community edition) | MongoDB |
|---|---|
| [OSS版のMariaDB](https://mariadb.org/)だと[データベースエンジンレベルでの用意](https://openquery.com/oqgraph-engine-for-mysql-mariadb-and-drizzle/)があるが<br>AWSのAuroraではサポートしていないそう<br>[SQL Server Graph Features](https://docs.aws.amazon.com/dms/latest/sql-server-to-aurora-mysql-migration-playbook/chap-sql-server-aurora-mysql.tsql.graph.html)<br><br><br><br><br> | [MongoDB as a Graph Database](https://www.mongodb.com/databases/mongodb-graph-database)を確認すると、ノード(頂点)、エッジ(リレーション)、プロパティ、ラベルを基本としてグラフ型のオブジェクトとその検索をサポートしている<br>graphLookupという、agrreegation piplineの機能を使うだけで簡単に利用できる<br>別途GraphQLなどのデータベースを用意しなくても利用できるようので使い勝手がいい |