第1回目となる今回は、まずMongoDBの概要と特徴的な機能を解説し、どのようなケースで有効に使えるかを紹介します。
NoSQLへの流れ
過去20年間でCPUの処理能力は数十倍になり、ディスクの1バイトあたりの金額は1000分の1になりました。開発環境はクラウドに移行し、扱うデータ量とWebサイトのアクセス数は大幅に増加しました。このような環境の変化から、データストアへ求められるものが変化してきています。
RDBでは、高トラフィックなWebシステムのバックエンドという箇所では、性能の限界があると考えられるようになってきました。その結果、RDBでは性能に限界がある適用箇所にNoSQLを補完することによって補おう、という流れが出てきたと考えています。
NoSQLの分類
現在NoSQLと呼ばれているものは、大きく分けて3つに分類されます。
- 1.KVS(Key-Value Store)
- データをKeyとValueのHash形式で持つ
- 基本的にはKeyでの完全一致検索でしかデータを取得できないが、高速に動作する
- 代表的なプロダクト:Memcached、Redisなど
- 2.ドキュメント指向データベース
- スキーマを定義しなくても使用できるスキーマレスである
- 複雑な検索条件でデータを取得することが可能
- 代表的なプロダクト:MongoDB、CouchDBなど
- 3.列指向データベース
- RDBのような行単位ではなく、列単位での処理に特化している
- 代表的なプロダクト:Cassandra、HBaseなど
この連載ではNoSQLのひとつでありドキュメント指向データベースに分類されるMongoDBについて紹介していきます。
MongoDBが目指すもの
MongoDBは、NoSQLの高パフォーマンス/スケーラビリティを保持しつつ、RDBライクな機能をバランスよく組み込むことを目指して開発されているドキュメント指向データベースです。従来のRDBが備えている一部の機能を制限することにより、KVSに近いパフォーマンスを実現させています。逆に言うと、KVSのパフォーマンスを多少犠牲にして、慣れ親しんだRDBの機能を実装しているという見方もできます。では、MongoDBは何を制限して、どんな機能を実装しているのでしょうか。
RDBと比較してMongoDBが実装しなかった機能は、トランザクションとリレーショナル(JOIN)です。これらの機能は場合によってはコストが高く、パフォーマンスを著しく劣化させる原因となると判断しました。また、開発者がデッドロックについて考えないで良いようなシンプルでわかりやすいシステムにしたいという目的もありました。MongoDBが目指す軽く速いデータベースのため、トランザクション・リレーショナル(JOIN)というRDBの代表的な機能を排除する選択をしました。
次にKVSと比較してMongoDBが備えている機能です。代表的なものに"RDBライクな検索クエリ"があります。memcachedなどに代表されるKVSは、基本的にkeyでの完全一致検索しかできません。MongoDBでは、RDBでいうwhere,likeを使った複雑な検索が可能です。またv2.2から集計処理に関する機能が追加され、SUM, AVGなどをgroup by, having, order byに相当するクエリと組み合わせて使用することが可能になりました。
上記の機能に加えて、インストールのしやすさ、主要なOS用バイナリの提供、多くのプログラミング言語用ドライバの充実から、他のKVSと比較して適用範囲が広く、導入しやすくなっています。つまり、あなたがMongoDBを使いたいと思ったら、すぐに使い始めることができます。
このように、RDBの一部機能を制限してKVSに近いパフォーマンス・スケーラビリティを実現していることを公式ドキュメントでは以下のような図で表しています
MongoDBの思想
MongoDBの思想を紹介するため、公式ドキュメントからMongoDBの開発元である10gen社CTO兼共同創業者Eliot Horowitzの言葉を引用します。
MongoDBは研究室の中で設計されたわけではありません。私たちは、大きなスケールの、高可用性を備えた、堅牢なシステムを構築した経験をもとにMongoDBを作りました。ゼロからはじめたわけではありません。何が壊れているのかを見つけ出し、それに取り組むという方法を取ってきました。
私はMongoDBについて、次のように考えています。もしMySQLのデータモデルをリレーショナルベースのものからドキュメントベースのものへ変更したら、管理が容易な高速な埋め込みドキュメントや、スキーマレスデータベースやアジャイル開発手法、ジョインが重要でなくなることによって容易になるスケールアウトなど、たくさんの素晴らしい機能を得るでしょう。
リレーショナルデータベースには、素晴らしい機能がたくさんあります。インデックスや、ダイナミッククエリや、アップデート機能など、枚挙に暇がありません。私たちはそこは大きく変えないようにしました。たとえば、MongoDBでインデックスを設計するときの手法は、MySqlやOracleでの手法と全く同じです。単に、埋め込みフィールドにインデックスを張るという新しい選択肢が与えられるのです。
MongoDB Docs-Japanese:はじめに
MongoDBはこのような思想に基づき、今日も開発が続けられています。
MongoDBの特徴
MongoDBの特徴として、以下のようなものが挙げられます。
- スキーマレスであるドキュメント指向データべースであること
- データはスキーマレスなドキュメントで格納され、任意のフィールドを好きなときに追加できる
- KVSでは苦手なValueを検索の条件としたり、ソート・集計を実現できる
- スケーラビリティに関する機能を標準機能として備えていること
- レプリケーション機能、オートフェールオーバー機能を備えている(Replica Sets)
- レンジパーティション機能、オートバランシング機能を備えている(Sharding)
- RDBと比較してRead/Writeの性能が高い
- トランザクション・リレーションを制限した結果、KVSに近いパフォーマンスを出せる
- 開発のしやすさ
- どのような環境でもパフォーマンスが出るように、ネイティブソケットプロトコルを使用したドライバを主要なプログラミング言語で開発元が提供している
- RESTインターフェイスを標準で備えており、Webで広く普及しているJSONを使用してデータ送受信ができる
このような特徴があるMongoDBは、どのようなケースで有効に使用できるのでしょうか。
MongoDBの使いどころ
MongoDBは先ほど紹介した特徴から、以下のようなケースで有効です。
Webサイトの操作データログの蓄積
MongoDBをログストアにする事例はすでにWeb上に多く見られます。データサイズの制限があるコレクションであるCapped Collectionや一定期間が経過すると削除されるTTL Collectionといった機能が活用されています。またアプリによって出力フォーマットが違うログを一括して扱う場合、スキーマレスであることが有効に働きます。
アドホックなフィールドを検索対象とするようなコンテンツ
たとえば、ユーザによって独自項目を定義できるようなシステム(アンケートシステムなど)の場合、スキーマレスであると柔軟に対応できます。また、それぞれの独自項目を検索対象にすることも可能です。
ソーシャルゲーム
軽いRead/Writeが大量にあるようなソーシャルゲームにはMongoDBは向いていると言えます。スケーラビリティ機能とレプリケーション機能も用意されています。
逆に以下のケースで適用したいというなら、もう一度検討してください。
銀行や会計システムのような、複雑なトランザクションに重きを置くシステム
複数のトランザクションを必要としたクエリが必要になる場合、MongoDBは向いていません。ただし、1つのドキュメントに対するAtomicな操作はサポートしていますので、ネストしたドキュメントを使用して設計を工夫することにより対応可能になります。
レガシーな夜間バッチの負荷がかかるビジネスインテリジェンスシステム
MongoDBはバッチ処理が不可能でこそないですが、リアルタイム処理のほうが得意です。
SQLを必須としているシステム
MongoDBはSQLをサポートしていません。(NoSQLなので)
それでは次に、実際にMongoDBをインストールして使ってみましょう。
MongoDBのインストール
MongoDBのインストールは非常に簡単です。以下の4つのステップで起動できます。
- MongoDBのバイナリダウンロード
- ダウンロードしたファイルの展開
- データディレクトリの作成
- MongoDBの起動
MongoDBのバイナリダウンロード
まずMongoDBをダウンロードします。MongoDBダウンロードページからそれぞれのプラットフォームに合ったものをダウンロードしてください。
注意:MongoDB2.2はWindows XPでは動作しません。Windows XPの場合は、MongoDB2.0系を使ってください。
本記事ではversion 2.2.1を使用します。
ダウンロードしたファイルの展開
ダウンロードしたファイルはzipやtar.gz等に圧縮されているので、好きなディレクトリに展開します。
展開したMongoDBのディレクトリは以下のようになっています。
データディレクトリ作成
データの格納に使うディレクトリを作成します。コマンドプロンプト(Linuxならターミナル)を起動し、以下の通りディレクトリ作成してください。
MongoDBの起動
展開したMongoDBのディレクトリにあるMongoDBの本体「mongod.exe」を実行してください。MongoDBクライアント「mongo.exe」と名前が似ているため注意が必要です。
起動したコンソールの最後に「waiting for connections on port 27017」と出力されれば起動成功です。
MongoDBに触ってみる
MongoDBクライアントでMongoDBのコンソールに接続する
新しくコマンドプロンプト(Linuxならターミナル)を起動し、展開したMongoDBのディレクトリにあるMongoDBクライアント「mongo.exe」を起動してください。
以下のように入力待ちの状態になれば接続できています。
MongoDBのデータ構造
データを挿入する前に、MongoDBのデータ構造について解説します。MongoDBは以下のようなデータ構造を取ります。
ですので、まずデータベースを作成し、次にコレクションを作成します。そのコレクションに対して、ドキュメントのCRUD操作(作成、参照、更新、削除)を行っていきます。
データベースの作成
MongoDBのコンソールに接続した状態で、useコマンドを使いデータベースを作成します。今回は「testdb」という名前のデータベースを作ります。
[参考]useコマンドはデータベースの指定にも使いますが、MongoDBでは存在しないデータベースを指定すると、データベースを新たに作成します。
ドキュメントの挿入
コレクションを指定して、insertコマンドでドキュメントを挿入します。今回は「testcoll」という名前のコレクションを作り、その中にデータを入れます。
何のエラーも表示されなければ成功しています。
普通のリレーショナルデータベースに対する挿入とはかなり異なると思うので、詳しく解説してきます。
まず、「db.testcoll.insert()」の部分ですが、「db」は指定したデータベースを表し、「db.testcoll」でコレクションを指定しています。そして、このコレクションのメソッドである「insert()」を呼び出しています。
次に、挿入するドキュメント「{ "key1" : "string", "key2" : 123 }」の部分ですが、これはJSON形式のハッシュデータです。JSONの説明は省略しますが、このようにMongoDBに対する操作は、すべてJSON形式のデータで扱います。
もう1つドキュメントを投入してみましょう。次に投入するデータはハッシュだけではなく、ハッシュと配列の混ざったドキュメントを入れてみます。
MongoDBはスキーマレスですので、このようにいろいろなデータをドキュメントとして格納できます。
ドキュメントの参照
ドキュメントの参照はコレクションのfind()メソッドを使います。以下のコマンドを実行してください。
このように先ほど挿入したドキュメントが表示されます。また、キー"_id"の値には、自動的に一意な文字列が採番されます。
findOne()のメソッドで、最初の1つのドキュメントを取得できます。
ドキュメントに対して、ハッシュキーを引数に渡すことにより、値を取り出すことができます。
この文法はJavaScriptと同じです。実はMongoDBはJavaScriptの実行環境を備えているため、JavaScriptと同じ文法を利用可能です。
今回はここまでとします。