読書メモ:はじめてのMongoDB
はじめに
MongoDBは、オープンソースのWebアプリケーションにおいてセッションデータやキャッシュデータの格納において、memcachedやRedisにならぶ選択肢として冗長化で使われることが良くあります。
自分も仕事において、MongoDBをmemcached、Redisに並びよく使ってきました。
memcachedおよびRedisは、より原始的なキーバリューストアという感じでパフォーマンス重視という印象に対し、MongoDBは、より汎用的なドキュメント指向データベースとして永続的にJSONデータを格納したり、Expressを使ってGUIでの管理がよりしやすい少し重厚なセットという印象を持っていました。(Redisも最近はかなり充実していますが・・・)
しかし、以前から使ってはいたものの自分でアプリを開発するという観点でじっくり勉強したことが無かったため、この本を購入しました。
NoSQL系は、RDBMSと違い基本的に学習コストが低く、割と簡単に使い始められるものが多くなっています。
この本でも160ページでCRUD処理からインデックスの作り方、アプリケーション開発・運用までコンパクトにまとまっており、非常にわかりやすいものでした。
今回は、特に印象に残った部分をまとめたいと思います。
更新処理にfindAndModify
を使った方が安全
リレーショナルデータベースと違い、NoSQL系のデータベースは、ACID特性が弱くなっています。
MongoDBでは、何も考えずに複数のプロセスから検索および更新を行うと思わぬ結果を招きかねません。findAndModity
を使えば、ドキュメントの検索処理と更新処理が1つとなるため、アトミックに実行されます。
これにより、他のプロセスで処理中に別の値に更新されてしまうことによってデータベースに一貫性がなくなることを防げます。
これを使わずに、find()
などの検索後にsave()
やupdate()
などの2ステップの更新処理使う際は、他のプロセスが検索(find()
)と更新(save()
やupdate()
など)の間に入り込むことがあるので注意が必要です。
また、算術演算をする場合は、Webアプリケーション側で算術結果を更新するより、MongoDBの算術演算機能($inc
など)を使うことでデータを直接演算します。
これにより、残高などの項目が2重書き込みによる更新で一貫性が無くなることを防ぐことができます。
インデックス
MongoDBもデータベースと同様にパフォーマンスを出すにはインデックスの作成が重要です。
デフォルトでは、_id
に対してユニークインデックスが付与されていますが、データベースのインクリメント型のidによるB+木インデックスとは違います。
また、デフォルトでの格納には、各コレクション内のデータに順番がありません。
そのため、例えばリンゴの価格が30円以上300円以下のデータが格納されたドキュメントなど特定の範囲検索などは非常に時間がかかります。
各ドキュメントに数値などがあるような場合において、インデックスを作成してソートしておくと範囲の検索でパフォーマンスが出そうです。
また、アプリケーションの用途に応じて複合インデックスを作成すればより早く検索できると思います。
データのインポート・エクスポート
MongoDBに興味があるものの格納したいJSONデータが無いかもしれません。
しかし、MongoDBでは、mongoimportおよびmongoexportを使ってTSV、CSVのインポート・エクスポートが可能です。
そのため、既存のデータベースのデータをMongoDBに取り入れて試すこともできますし、MongoDBのデータをリレーショナルデータベースへ取り込むことも可能です。
この機能を使えば、学習に使えるだけでなく、アプリケーションでNoSQLの特性に応じてリレーショナルデータベース連携しつつ使うこともできます。
冗長化およびスケーリング
レプリカセットの作成は、設定が簡単そうでした。
3つのデータベースに冗長化して、負荷分散や無停止のバックアップ構成ができそうです。
しかし、データベースを分割するシャーディングにおいてはより管理が難しくなりそうです。
理由としては、シャード内のチャンクが移動するリバランス等の処理がコンピューティング敵にもネットワーク的にも重くなるからです。
また、貧弱なオンプレミス環境の場合においては、信頼性の問題もあるので、シャーディングが必要なぐらいにデータボリュームが多くなる状況においては、Azure Cosmos DBなどのクラウドDBaaSに移行したほうが管理がしやすく安全と言えそうです。
スキーマレス
MongoDBは、スキーマレス(動的スキーマとも呼ばれる)なので、スキーマを定義する必要が基本的にはありません。
しかし、GraphQLなどと組み合わせるとより応用的なグラフスキーマを持たせることができます。
この部分が、GraphQLでMongoDBが好まれて使われている点かもしれません。
まとめ
以上、MongoDBは学習コストが非常に低く、コンソールよりもアプリケーションを通して使われることが多いと思います。
そのため、安全な更新処理や、パフォーマンスを向上させるインデックスの作成、運用管理において、きちんと機能を把握していない部分も個人的にありました。
この本は、コンパクトにまとまっており、非常に参考になるのでお勧めの本です。
ここまで読んでくださりありがとうございました。