「NoSQLデータベース」と呼ばれるものの中で、あまり目立たないがよく見ると面白い機能を搭載しているCouchDB。この連載ではCouchDBの役立つ場面を紹介していく(編集部)
「CouchDB? 名前は聞いたことある、ドキュメント指向、JSON……、特徴も何となく分かっている、だけど、どんな場面で使うの?」
CouchDBについて、こんなイメージを持っている方は多いでしょう。この連載ではサンプルアプリケーションを作りながら、「こんなときこそCouchDB!」という活用例を解説していきます。
連載「ゆったリラックス! CouchDBがあるところ」でもCouchDBの特徴を解説していますが、あらためてCouchDBについて、リレーショナルデータベース(RDB)と比較しながらご説明します。
RDBには長い歴史と実績があり、現在では「データベース」と言えばほとんどの人がRDBを思い出すほどです。しかし、どんな要求にも応えられる完全なものなど存在しません。これはRDBにも言えることです。
RDBは、正規化したテーブルにデータを格納するようになっており、必要に応じて取り出せます。しかし、正規化したデータが大きくなっていき、膨大な量になると、データを取り出すときに問題が発生します。複数のテーブルを結合(Join)して、データを取り出すときに処理性能が低下してしまうのです。
また、テーブルの列などの構造(スキーマ)を一度定義してしまうと、これを変えるのが難しくなります。つまりRDBは、あらかじめ構造が決まっているデータ以外は格納しにくいのです。
正規化したデータの処理性能の問題や、スキーマを変えにくい、スキーマ定義に従わないデータを格納できないなど、RDBが抱える問題が目立つようになり、最近はRDBの抱える問題を解決することを狙ったデータベース管理システムが登場しています。一般に「NoSQL(Not Only SQL)データベース」と呼ぶものです。
処理性能を追求するタイプのNoSQLデータベースとしては、Key/Valueデータストア、列指向データベースなどがあります。一方で、スキーマ構造にとらわれない、自由な形のデータを扱うことを目指したNoSQLデータベースとして、ドキュメント指向データベースがあります。CouchDBは、ドキュメント指向データベースの1種です。
CouchDBは、データ(ドキュメント)をJSON(JavaScript Object Notation)形式で保存します。RDBのようにあらかじめスキーマを定義する必要はなく、JSONオブジェクトをそのまま保存できます。JSON形式のデータは、配列や連想配列を保持できるので、繰り返し要素を保存するために別のテーブルを作成するような作業は必要ありません。また、ドキュメントの更新履歴をリビジョンという形で保存しています。
下に示したのは、都道府県の男女別人口をなどのデータを保存したJSONドキュメントのサンプルです。CouchDBではバイナリデータをドキュメントに添付できるので、県章のPNG画像ファイル(emblem.png)を添付してみました。
{ "_id": "Kanagawa", "_rev": "2-33800f007105d4d32afa40fc9b9dad1a", "type": "prefecture", "name": "神奈川県", "population_female": 4517279, "population_male": 4544194, "district": "関東地方", "_attachments": { "emblem.png": { "content_type": "image/png", "revpos": 2, "digest": "md5-y0il+Gf7UecfOFpoNLdUew==", "length": 9792, "stub": true } } }
CouchDBでデータを検索するときは、Viewを利用します。ViewはJavaScriptを使って、MapReduceの考え方で記述します。MapReduceはApache Hadoopで有名になったプログラミングモデルで、ドキュメントの情報を解析し、Key/Valueのペアを抽出するMap処理と、Map処理の結果から、同一のキーを持つペアを集計するReduce処理でデータを処理するものです。
前述の都道府県ドキュメントの人口データを抽出してみましょう。Mapプログラムは以下のようになります。
function(doc) { if(doc.type == 'prefecture'){ emit([doc.district, doc.name, "男性"], doc.population_male); emit([doc.district, doc.name, "女性"], doc.population_female); } }
最初にdoc.typeを判定しているのは、同一のデータベースに都道府県以外のドキュメントも格納できるため、都道府県以外のデータを処理対象としないようにしているのです。Reduceの段階で段階的に集計できるように、キーとして地方、県名、性別を指定しています。
以下のサンプルコードがReduceプログラムです。人口の合計を計算するsum関数だけを記述してあります。
function(keys, values, rereduce) { return sum(values); }
このViewの結果を見てみましょう。以下のURLにアクセスすると、JSON形式でViewの結果を取得できます。
http://localhost:5984/japan/_design/japan/_view/populations?group_level=1
結果は以下の通りになります。
{"rows":[ {"key":["関東地方"],"value":42688508} ]}
CouchDBにおけるViewの動作がイメージできましたか? 結果を参照するときに"group_level"を変えることで、より詳細なデータを見ることができます。先ほどは"group_level=1"として実行しました。今度は"group_level=2"で実行してみましょう。
{"rows":[ {"key":["関東地方","千葉県"],"value":6210707}, {"key":["関東地方","埼玉県"],"value":7263549}, {"key":["関東地方","東京都"],"value":13188831}, {"key":["関東地方","栃木県"],"value":1999972}, {"key":["関東地方","神奈川県"],"value":9061473}, {"key":["関東地方","群馬県"],"value":2008068}, {"key":["関東地方","茨城県"],"value":2955908} ]}
"group_level=3"で実行すると、次のようになります。
{"rows":[ {"key":["関東地方","千葉県","女性"],"value":3116776}, {"key":["関東地方","千葉県","男性"],"value":3093931}, {"key":["関東地方","埼玉県","女性"],"value":3612815}, {"key":["関東地方","埼玉県","男性"],"value":3650734}, {"key":["関東地方","東京都","女性"],"value":6668496}, {"key":["関東地方","東京都","男性"],"value":6520335}, {"key":["関東地方","栃木県","女性"],"value":1006775}, {"key":["関東地方","栃木県","男性"],"value":993197}, {"key":["関東地方","神奈川県","女性"],"value":4517279}, {"key":["関東地方","神奈川県","男性"],"value":4544194}, {"key":["関東地方","群馬県","女性"],"value":1020049}, {"key":["関東地方","群馬県","男性"],"value":988019}, {"key":["関東地方","茨城県","女性"],"value":1482593}, {"key":["関東地方","茨城県","男性"],"value":1473315} ]}
ここでは、JavaScriptで記述したMapReduceのコードをお見せしましたが、追加プログラムを用意すれば、ほかの言語で記述したMapReduceを処理させることもできます。CouchDBのWikiを見ると、ほかの言語でMapReduce処理を記述する方法の説明があります。
MapReduceのほか、全文検索エンジンApache Luceneやelasticsearchと連携することもできます。CouchDBでこれらの全文検索エンジンを利用するには、couchdb-luceneや、CouchDB Riverといったライブラリを利用します。couchdb-luceneの利用例については連載「ゆったリラックス! CouchDBがあるところ」の第4回を参考にしてください。
CouchDBでは、ドキュメント保存、更新、削除、検索といった操作にはRESTful APIを利用します。つまりWebブラウザや、Linux/UNIXの「curl」といった、HTTP(HyperText Transfer Protocol)のやりとりができるプログラムであれば、特別なドライバを用意することなく、そのプログラムからCouchDBを操作できます。
さらに、CouchDBにはJSON形式のドキュメントを整形して一覧表示する「list」と、詳細表示する「show」という機能を備えています。これらの機能を利用すれば、JavaScript、HTML、CSSを利用した簡単なWebアプリケーションを、CouchDB単体で実現できてしまいます。CouchDB単体でWebアプリケーションを作成する方法については、連載「ゆったリラックス! CouchDBがあるところ」の第2回を参考にしてください。
CouchDBはHTTPを利用したレプリケーション機能を備え、複数のサーバ間でデータを同期させることができます。この仕組みを利用すると、複数のCouchDBインスタンスとクライアントの間にNginXなどのロードバランサを配置し、負荷を分散させることができます。
CouchDBでは、1つのドキュメントが複数のサーバで同時に更新されると、それぞれのリビジョンを保持します。このような処理方法をMVCC(Multi Version Concurrency Control)と呼びます。CouchDBが自動的にマージするのではなく、ユーザーにデータの競合が発生していることを伝え、マージする手段もユーザーに委ねる形となっているのです。
CouchDBはサーバやPCだけでなく、AndroidやiOSを搭載したスマートフォンでも動作します。そして、携帯機器で動作するCouchDBのデータベースと、サーバ上のデータベースの間で簡単にデータのレプリケーションができるようになっています。
2011年10月、NTTドコモの海外拠点の1つであるDocomo Innovationsは、Couchbaseという企業と提携を結ぶことを明らかにしました。Couchbaseは、CouchDBを改良したデータベース管理システムを開発している企業です。
Docomo Innovationsは提携を結んだ理由として、Couchbaseが携帯機器からクラウド環境まで、多様な環境で利用できるデータベース管理システムを提供していることを挙げています。オフライン時は携帯端末内で動作し、オンライン時にサーバとデータを同期(レプリケーション)するシステムを容易に構築できるということです。
Copyright © ITmedia, Inc. All Rights Reserved.