MySQL
nosql
Firebase

NoSQL は Poor SQL?


はじめに

NoSQLに関して、MongoDBやElasticseacrch、FirebaseのRealtimeDB, Firestoreなどあれこれ触ってみたり調べたりしました。その上でNoSQLとSQL(リレーショナルDB)の両者に対して感じたことを書きます。

結論としては、NoSQLは明確な用途が無い限り基本的には避けられるべきものだと思いました。


SQLのジョイン便利

NoSQLにはジョインが無いので不便です。Nosqlでジョインせずにデータをネストさせると、1リクエストのデータ量が多くなります。また、検索性を考慮するとネストさせずにデータを分割する事になり、データの二重管理を避けるためにSQLのジョインに相当する処理を擬似的に再現する必要性が出てきます。ジョインに相当する処理をするとリクエストを二度送る事になり、リクエスト量・データ取得のための時間が増えます。最初からリレーショナルDBを使った方が良かったというケース多数です。


処理速度はケースバイケース

特に変わらず。NoSQLはジョインがないのでサーバーを並べて並列処理ができてスケールできて処理が早くできると言われているようですが、よくよく調べてみるとSQLでもジョインしなきゃ条件は同じようです。

参考


NoSQLなのにORMを結局使う

上のジョインにも繋がるのですが、MongoDBでMongooseという、Ruby On RailsのORMに相当するインターフェイス再現したライブラリーがほぼデファクトになっているようです。スキーマもリレーションも定義します。ようするにNoSQLじゃ使いづらいからRDBMS的に使いたいという事です。インターフェースはRDBMSですが、中身はNoSQLで無理やり処理しているので、リレーショナルでないNoSQLのデメリットだけが残る事になります。つまりはじめからRDBMS使った方が良かったという結論がデファクトスタンダードになっているのです。


NoSqlはDB設計むずい

例えば、 チームに複数のユーザーが所属している場合、RDBMSではuserテーブルとteamテーブルを持ち、userテーブルにteam_idを持つ設計のほぼ一択です。

NoSqlでは、一度のリクエストでデータを取得できるようにteamドキュメントにユーザーを直接ネストさせる事と、チーム情報を介さずにユーザー情報だけを一覧で取得するという検索性がトレードオフを考えて設計します。ケースバイケースで設計が安定しないです。ネストさせ1ドキュメントにデータを持つ、データを重複して持つ、RDBMS的な設計にするの3パターンのトレードオフがあります。


NoSQLはトランザクションが無くデータの整合性が取りずらい

データの整合性を諦める事でDBを並列にいっぱい並べられるようにしているのがNoSQLです。しかし、人間の頭ではデータの整合性が担保されないDBを扱うのは結構難しいです。NoSQLがトレードオフのために手放した整合性をクライアント側のプログラムで必要に応じて構築し直す必要があります。結構きついでしょう。


NoSQLはスキーマを定義せずに動的にデータをブチ込める

RDBMSと違って、user {name: 'taro'}とuser {first_name: 'taro'} を同じコレクション(RDBMSのテーブルに相当する)にぶち込んでも良いですが、不揃いなデータだと集計や一覧性など使い勝手が悪いので、基本的にスキーマは定義したくなるのが人情です。しかし、特定の場合にはスキーマレスが嬉しいケースもあります。例えば、Elasticsearchはグーグル検索のような全文検索のためのDBですが、検索キーワードを引っ掛けるためにとりあえず不特定のキーとデータをぶち込んで検索で引っ掛けるのはとても理にかなっています。


結論

NoSQLはかなり厄介です。RDBMSの多数の機能を諦めてトレードオフを取ったのがNoSQLで、結局その捨てたものをユーザー側がどうにか埋めようとする事になるのがほとんどです。明確な理由が無い限り基本的にRDBMSを使うのが吉でしょう。ちなみにFirebaseのリアルタイムデータベースは彼にしか出来ない役割が多く非常に便利です。