KVS(キーバリューストア)の特徴を利用する


Google App Engine(以後GAE)はデータストアという一種のデータベースを用いて、データの保存(永続化)を行います。
本サイトでも下記リンクでその方法について解説しています。

このデータストアは特徴として、RDB(リレーショナルデータベース)ではなくKVS(キーバリューストア)というデータ管理方式をとっています。

リレーショナルデータベース(RDB)は、データベースの各テーブルに役割を持たせてテーブル間に関係性を与えることで、一つのデータを役割毎に複数のテーブルに分割して管理します。

キーバリューストア(KVS)は、こちらもデータの管理方式の一つで、名前からイメージできるように「キー」と「値」という関係でデータが保存されます。KVSでもテーブルに似た概念(カインドという)は存在し、GAEのデータストアでも、JDO(JDOをGAEのデータストアに保存/取得する)を用いることでRDBライクにデータを扱うことができます。

今回は、このKVSにデータを保存する際の特徴について、RDBとの違いを交えながら解説したいと思います。

それでは続きをどうぞ

RDBおよびKVSへのデータ保存

RDBでは、あらかじめ各テーブルにカラムが定義されており、カラムの定義(型やカラム数)に沿ったデータの保存が求められます。

一方データストア(KVS)では、「キー」「値」という関係でデータが保存され、カラムを意識する必要はありません。

RDBの方については特に違和感はないと思います。テーブルに定義されたカラム数以上のデータ、またカラム毎に定義された型と違ったデータは保存できません。
KVSについて、サンプルを用いて具体的に見て行きます。
今回は以下のようなサンプルを用意し、データストアに3つのエンティティー(いわゆる行、レコード)を作成してみます。
データストアへのデータの保存方法については、「Low Level APIでGAEのデータストアにアクセスする」を参考にしてください。

KvsTestServlet.java

public class KvsTestServlet extends HttpServlet {
	public void doGet(HttpServletRequest req, HttpServletResponse resp)
	throws IOException {
		DatastoreService dss = DatastoreServiceFactory.getDatastoreService();

		Key key1 = KeyFactory.createKey("kvs",1);
		Entity entity1 = new Entity(key1);
		entity1.setProperty("name", "seit");
		entity1.setProperty("age", 25);
		entity1.setProperty("gender", "man");
		dss.put(entity1);

		Key key2 = KeyFactory.createKey("kvs",2);
		Entity entity2 = new Entity(key2);
		entity2.setProperty("name", "kobashing");
		entity2.setProperty("gender", "man");
		entity2.setProperty("pastime", "golf");
		dss.put(entity2);

		Key key3 = KeyFactory.createKey("kvs",3);
		Entity entity3 = new Entity(key3);
		entity3.setProperty("name", "mhidaka");
		entity3.setProperty("attribute", "hitsuji");
		entity3.setProperty("gender", "man");
		entity3.setProperty("join", "Techbooster");
		dss.put(entity3);
	}
}

データ保存方法の詳細な解説は前述のリンクにお任せするとして、ここでは簡単に解説しておくと、
まず6行目でエンティティーのキーを生成しています。
7行目で生成したキーを用いてエンティティーを生成しています。
8、9、10行目で、EntityクラスのsetProperty()メソッドを用いて、エンティティーのプロパティー(列名:第1引数)とその中身(値:第2引数)を指定しています。
11行目でDatastoreServiceクラスのput()メソッドを用いて、生成したエンティティーをカインドに保存(永続化処理)しています。
なお、カインド名は6行目のキー生成時にKeyFactoryクラスのcreateKey()メソッド第1引数に指定した文字列となります。
あとは6〜11行目と同じ処理(プロパティーは異なる)を3回行うことで、3つのエンティティーを生成、保存しています。

さて、各エンティティー(entity1、 entity2、 entity3)に格納しているデータを見てみると、entity1にはnameagegenderというプロパティーでデータを保存しているのに対し、entity2ではageがなく、代わりにpastimeというプロパティーが定義されています。
またentity3では、attributejoinというプロパティーが存在し、プロパティーの数もentity1およびentity2と異なります。
このような状態で保存した場合でも問題なく保存は完了し、データストアでは以下のような状態でデータが保存されています。

見た目はまるでRDBのようですが、例えば一行目のエンティティーには、pastime、attribute、joinのプロパティーは存在していません。
通常のRDBでは、基本的にテーブルにカラムが決められているため、エンティティー(RDBではレコード)毎に違ったプロパティー(RDBではカラム)でデータを保存しようとすると、カラムが存在しないということでエラーになります(上図参照)。
また、型についても各エンティティーの各プロパティーで指定できます。
例えば今回のサンプルの場合、各EntityのnameプロパティーにはString型の値を保存していますが、2行目のエンティティーのnameプロパティーにだけIntegerの値を保存する、といったことも可能です。
つまり、同じカインドでも各Entity間に関係性があるわけではなく、あくまで「キー」と「値」の関係で成り立っているのです。

さて、今回はデータストア(KVS)にデータを保存する際の特徴について解説しました。
KVSはRDBに変わるデータ保存の方式として注目されているので、この機会にGAEで勉強してみるのもいいのではないでしょうか。

One Comment