NoSQLのメリットデメリット(couchDBを業務用アプリに適用したらこうなった)

実際にNoSQL(couchDB)をウェブアプリケーション組み込んでみたという話。





NoSQLとは



RDB以外のデータベースを指す。

・キーと値を持つキーバリューストア
・1つのデータがjsonやxmlになっているドキュメントストア
・グラフ型
などがある

couchDB(今はcouchBase?)はjsonタイプのドキュメントストアになる。


とある案件でcouchDBを使おうという話になって、
私も興味があったので実際のプロダクトに組み込むことになった。
その時の経験をまとめてみた。



















概ね上記画像のようになった訳だが
いわゆる出落ちというやつだが

画像は
https://pixabay.com
より
google画像検索のライセンスフィルタ便利。





couchDBのメリット・デメリット



  • 検索条件が多くなる場合は使わないほうがいい
  • 厳密な文字列検索が必要な場合は使わないほうがいい
  • RDBでいいときはRDBを使う
  • RDBで辛い実装がNoSQLだと絶対に楽になるというわけではない
  • やろうと思えばNoSQLでも出来ないこともなかったが世の中には頑張らないほうがいいこともある



以下詳細。
テーブル ≒ Viewに近い表現で書いているところがある。


そもそも非構造データである必要はあるのか


データが非構造で何でも入れられるから良いというのは果たして真なのか。
PHPやJavaScriptは型がないので便利と言っているようなものなので、この辺をメリットに感じる人とは分かり合えないと思う。
例えばデータをJavaScriptで扱いたいとなったときにundefined.xxxx にアクセスすると落ちるので毎回値のチェックが必要。
あるいはどこかのタイミングで整備するか。

その場しのぎの対応を繰り返して誰にもメンテできない状態になるかもしれない。



couchDBの特徴の一つに画像や音声などを添付することができる


が結局データ取得時にそれぞのファイルを取得してこないといけないしRDBでファイルパスを値として持たせるのと何ら変わりないように感じる(物によってはBlobで十分)
couchDBはファイルをそのままファイルとして保存できるが、例えばNode.js上だと手間としてはあまり変わらなかった。
つまり使う側としてはメリットを全く享受できなかった。しかもデータ+ファイル数分だけリクエストを投げないといけないのであまりパフォーマンスが良くない。



制約について


View作成時にこの辺りは調整できる。
がMap Functionでこのキーに値が入っていなかったら弾く、あるいは初期値を設定するなどを記述しないといけなくなるしその定義ははっきり言ってアクセスしにくいので確認するのがかなり面倒になる。
javaScript式なのでテスト対象も増えるが複雑になるとそれも難しくなってしまう。


厳密な文字列検索が難しい

例えばクエリが商品名に引っかかるデータをすべて持ってくるときなど
詳細は https://trueman-developer.blogspot.com/2018/03/couchdb.html を見てほしい。


Joinについて


Join1つならいける(場合によっては出来ない)
Join複数も可能だがあまり直感的でないし複雑になってしまう。
また用途の数だけViewが増える(RDBでいうとSQL文が増えるごとにViewが増えるようなイメージ)


ユニオンについて


NoSQLではRDBでは難しいUNIONが容易にできる。
構造が違うデータ(例えば生鮮食品マスタと加工食品マスタとかいかにもカラムが変わりそうなテーブル)をまとめて一つのViewにまとめることができる。



トランザクション


これはよく言われるのでNoSQLを使おうとなったら考慮には入っているはず。入っていないなら大人しくRDBを使うこと。
ロックは自前で実装できないこともないが基本的に設計あるいは用途が間違っていると考えたほうが良い。
データをまとめてバルク処理して更新に失敗したらリトライすると言う設計にすると概ねうまくいく。
トランザクションを実装するくらいならRDBを使う。



複数データ間の整合性


なかなか難しい。トランザクションを再発明するようなことになりかねない。
複数データだけでなく削除対象がデータを取得してきて削除するまでの間に更新されたりすると削除されずに残ったりする。



正規化するのかしないのか


一般的にはNoSQLは正規化しないやり方を推奨されているらしい。
ただしデータ構造によっては1ドキュメントのデータが大きくなりすぎてパフォーマンスに影響が出るケースがあった。
クエリ数は増えるが関連データを持たせずに参照の都度引っ張ってくることも考える必要があるかもしれない(あるいは頑張ってJoinするとか)



データ構造変更に弱い


NoSQLは構造変更に強いとか言った人誰?
RDBはそれほど構造変更に弱くないしNoSQLはそれほど構造変更に強くない。
NoSQL構造が柔軟で不定ということはそれはつまりプログラム側で何とかしろということになる。とても構造変更に強いとは思えない。
恐らくスケーラビリティ的な話が曲解されたものだと思う。



検索条件を増やすごとにテーブルを1つ追加するくらいの労力が必要


複数条件の検索を素直に対応しようとすると検索条件の組み合わせの数だけViewが必要になる(A,Bの2つならA・B・ABの3通り、A,B,CならA・B・C・AB・BC・AC・ABCの7通り)。
ある程度ザクッと取ってきてプログラム上で絞り込む処理などが必要になる。
Viewのサイズを増やしすぎないようするとか、より絞り込まれる条件になるようにどのViewを利用するかとかパフォーマンスとかを考える必要がある。
実際に本番運用したら想定と違う使われ方をしてパフォーマンスが出ないケースも考えられる。



追加処理は高速


ただのjsonなので追加処理は爆速。
バルクインサートを利用すれば数十万件が数秒で終わる。
ただしViewの生成にそれなりに時間がかかるので物によっては結局利用できるようになるまでに少し掛かってしまう。
データが特定できてさえいれば更新、削除も同様に高速。



メンテが辛い


うっかり間違ったデータを投入してしまったときに、RDBならSQLを書くだけでメンテできるがNoSQLだとなかなか難しい。
実際のところは慣れればそれなりの速度でスクリプト(何でもいい。サーバに合わせてTypeScrptで記述していた)を書けるのだが、習熟に時間がかかるしSQLと違ってあまり潰しが効かない。


ノウハウがない


実際のところNoSQLに詳しいと言うわけではないので上記の対応方法はあるのかもしれない。
RDBはノウハウがある程度溜まっているのに対してNoSQLはノウハウが少ない(そもそも種類によって別物)ので最適な設計をするということ自体が難しい。


何に向いてる?


ログ、掲示板、チャットなどはおそらく最適。
とりあえずためておいて後で整備してRDBへいれるといった使い方もあるかもしれない。


勘違いしないように補足すると用途に適合する場合にはとても良いものであるということ。
別のプロダクトでは自分の意思でNoSQLを選択してうまくいっているということ。
つまりNoSQL自体悪いものでなく明らかに要件にあっていないのに選択した人に罪があるということ。
ちなみに爆発炎上した件のプロジェクトだがそれなりの休暇を犠牲にしてまともに動くものをリリースした。
ただし運用がかなり厳しいらしくしかもそこそこいい感じに動いているがゆえにDB変更の予算も下りないという悲劇的な状況になってしまった。




参考


http://www.publickey1.jp/blog/10/nosqlrdbpartake.html
http://d.hatena.ne.jp/m-hiyama/20130727/1374900010



2018年6月26日火曜日