spacelyのブログ

Spacely Engineer's Blog

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

はじめに

株式会社スペースリー Railsエンジニアの海老原です。 スペースリーではメインのデータベースとしてMySQLを採用していますが、今後、MongoDBの活用も視野に入れて検討をしています。 最適な活用方法を日々模索するなかで、一覧形式で機能を比較検討したいと思いまとめました。

スペースリーでは、マスタの系のデータでは既にRDBによるデータ設計がなされています。
RDBの世界では先にエンティティとリレーションシップを用いたデータ設計を行い、正規化を経てテーブルという実態に落とし込みます。
事前に、各オブジェクトの役割や関係性が明確になっていることが前提です。
一方で、試行錯誤して開発するアジャイル体制の開発現場では、データの役割や関係性が変化することがしばしば起こります。
データ構造の変更に対する柔軟性が乏しいRDBではスキーマ変更の対応をするのに時間がかかってしまいますので、スキーマレスのDBを使う事で、実際のデータを素早く追従させる事が狙いです。

いきなり全てのデータをスキーマレスのDBに載せ替えるというのは現実的ではなく、データの性質によって使い分ける事が重要です。
なので、今後、現在の巨大化したサービスをサブシステムやマイクロサービスに分割していく段階で、少しづつ導入を進めていく形になっていく事になると思います。

それぞれの特徴

リレーショナルDB(MySQL) ドキュメントDB(MongoDB)
データ構造 テーブルという表計算ソフトのような構造。正規化という手法を用いて適度に重複が発生しない構造(テーブル)を事前に定義する。 正規化は1-3段階まであり厳密な設計思想が存在する。 JSON形式 スキーマレスなので事前に全ての定義をする必要はない。緩やかな設計思想で、JSONモデリングを行う。主キーは自動採番で後からインデックスの設定もできる。遅いけどコレクション結合もできる。
処理速度 インデックスの効率に依存する。細かいメモリチューニングができる。HDDに書き込むオーバーヘッドがある。 インデックスはRDB同様に利用できる。インメモリで動くためオーバーヘッドが少なく高速。データの集計などの単純計算はRDBよりも高速にできる。
特性 ☆ACID特性という原則を守る事ができる
※ とても厳格なので金融や基幹システムなどに向いている
☆Base特性という原則を守る事ができる
※ ゲームのセーブデータや粒度の細かい操作ログ記録などに向いている
分散性 NDBクラスタという特殊なテーブルを使う以外には基本的にレプリケーションを利用した読み込み分散のみ シャーディングとい機能を利用して書き込み分散ができる

分散化アーキテクチャ

垂直分散 水平分散
MySQL(レプリケーション) MongoDB(シャーディング)
スレーブがマスターのリレーログを読みに行って自分のデータベースに情報を書き込む。
master ⇐> slave間の整合性を保持するための禁忌事項がいくつかある。
例: 日付を指定した削除更新クエリを発行してはいけないなど
シャーディングしているどのノードにも書き込みができる。
mongosはキーを元にルーティングをしているだけ。
1つのシャードがダウンした場合にデータを転送して別のシャードで復元できる。

※ MongoDBレプリカセットの話は一旦省略しています。 詳しくは、こちらをご覧ください
MySQLでは、マスタースレーブという呼び名が廃止され、マスター -> ソース、スレーブ -> レプリカという呼び名に2020年から統一されています。(本記事では引き続き旧式の名称を利用しています。)
https://dev.mysql.com/blog-archive/mysql-terminology-updates/

SQL構文の比較

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

MySQL MongoDB
1. スキーマ定義
create table customers (
id number(10) not null primary key,
name varchar(40) not null,
tell varchar(40) not null,
)

2. データの投入
insert into customers(id, name, tell) values(null, ‘test’, ‘080-0000-0000);’

3. カラムを増やす
alter table customers add address column varchar(255);

4. データの投入
insert into customers(id, name, tell) values(null, ‘test’, ‘080-0000-0000);’
1. コレクション定義
db.createCollection( "customers")

2. データを入れる
db.customers.insert([{name: ‘test’, tell: ‘080-0000-0000’}])

3. カラムを増やしてデータを入れる
db.customers.insert([{name: ‘test’, tell: ‘080-0000-0000’,address:’Tokyo’}])








利用例

MySQL MongoDB
ECサイトなどの商品管理
重複なく設計されたマスタ系のデータテーブルを保管して参照する

■銀行システム
厳格なトランザクションの下で、入金、出金、振り込みなどの操作を行わなければならない
■大量のログ保管
ヒートマップデータやアプリ操作ログなどの保管や統計的集計

■ゲームのセーブデータ
特定個人のプレイデータで厳密排他制御の必要性がない

Railsを利用しないアーキテクチャ実例(MongoDB)

マネージドサービスの活用

〜 例: 視聴ログなどの蓄積にマイクロサービスを利用する場合 〜

AWS
MongoDB Atlas serverless architecture
AWSを利用したマイクロサービスのアーキテクチャ
APIGateway経由でデータを登録したり、他のAWSのサービスと組み合わせたマイクロサービスの開発が可能
既にAWSを利用している事業者向け

■Atlas
Microservices with MongoDB Atlas
MongoDBの提供するマネージドサービス
データベースとそのWebのクライアント、APIのエンドポイントまで作成して利用できホスティングも提供しているサービス
サーバー構築の手間をすべて省きたい場合に有用

クライアントツールの活用

〜 例: 蓄積されたデータの閲覧ツールを実装せずに閲覧する場合〜

■ Studio
Studio 3T(GUI client)
MySQLだとnavicatというツールがあるがそれと同じようなもので
クエリさえ分かればデータが引き出せるというもの

■HumongouS.io
HumongouS.io(Web GUI )
上記のWeb版

積極的に活用していきたい新機能

ジオコーディング

MySQL MongoDB
MySQLにも空間データを扱う型が存在する。PointやPolygonなどの複雑なGeometryもサポートしている。
空間データ型
緯度経度
MongoDBでは、複雑なGeometry(点、直線、多角形)をlon/latで扱うものと、2Dの座標空間を扱えます(点、四角、多角形、円、Sphere)
球面空間でのクエリもサポートしている。
Geospatial Queries
どちらも、緯度経度による空間データを扱えるので、近隣の施設などを検索することができます

グラフ表現

MySQL(MariaDB community edition) MongoDB
OSS版のMariaDBだとデータベースエンジンレベルでの用意があるが
AWSのAuroraではサポートしていない。
SQL Server Graph Features

MongoDB as a Graph Databaseを確認すると、ノード(頂点)、エッジ(リレーション)、プロパティ、ラベルを基本としてグラフ型のオブジェクトとその検索をサポートしている
graphLookupという、aggregation pipelineの機能を使うだけで簡単に利用できる

最後に

spacelyでは一緒に働いてくださる方を大募集中です。
Web系エンジニアの他にも、インフラ、アプリ、ディープ・ラーニングなど幅広い分野でエンジニアを募集しています。
詳しくは採用サイトをご覧になってください!