同一テーブルでプロパティ項目を変更して永続化
1. プロパティ項目が異なるエンティティを登録
App Engineのデータ・テーブル*1には、RDB(Relational Database)にはないデータ構造上の主な特徴が、2つあります。その1つが、今回紹介する「プロパティ項目の可変性」で、もう1つは次回紹介予定の「プロパティ項目のコレクション・フィールド定義」です。
- [*1] App Engineでは、ユーザー・データを格納するテーブルを「kind」と呼ぶことがありますが、ここではテーブルの名称を統一して使用します。
1.1. プロパティ項目の可変性
それでは、プロパティ項目の可変性とは、どのようなものでしょうか。
RDBの場合、テーブルの列項目は、スキーマ(概念スキーマ)で定義されています。テーブルに登録されるレコードごとに列項目の種類や属性、列項目数を変えるようなことはできません。
この一方で、データ構造がキー・バリュー型になっているApp Engineのテーブルでは、キー(インデックス)項目以外で、このような変更を任意に行うことができます。
[可変プロパティ項目の例]
例えば、図1のように、3人の従業員情報をApp Engineのキー・バリュー・ストア(KVS)に登録するとします。
図1: 従業員情報をApp Engineのキー・バリュー・ストアに登録する |
キー(インデックス)項目以外は、登録するエンティティ(≒レコード)ごとにプロパティ(≒RDBの列項目)の項目数が異なっています。また、データ型も、文字列型のほかに、日付、論理、整数型などが含まれており、プロパティごとにそれぞれ任意に指定できます。これは、テーブルの列項目がスキーマによって一意に定義されてしまうRDBでは不可能なことです。
[プロトコル・バッファとキー・バリュー・ストア]
それでは、App Engineのデータ・ストアでは、なぜこのような任意のプロパティ定義が可能なのでしょうか。ユーザー・データ(エンティティ)がデータ・ストア内に永続化されるまでの内部処理について、次に説明します。
図2: プロトコル・バッファでのシリアライズ処理と永続化(クリックで拡大) |
ユーザー・データは、図1のような形でそのまま永続化されるわけではありません。プロトコル・バッファ*2によってエンティティ・データをシリアライズ・圧縮した後で、永続化されます。
- [*2] プロトコル・バッファは、言語やプラットフォームに依存せずに構造化データをシリアライズする、Googleによる拡張可能なメカニズムです。XMLに似ていますが、XMLよりもコンパクトで、高速で、シンプルです。データをどのように構造化するかを一度定義すれば、特別に生成されたソース・コードを使い、構造化データをさまざまなデータ・ストリームに対して容易に読み書きできます。さまざまな言語 (Java、C++、Python)から使えます。
図2は、図1のデータがデータ・ストアに永続化されるまでの、データ形式の変化を現しています。
図2の(1)では、App Engineのユーザー・プログラムから、永続化データがセットされています。それぞれのプロパティ項目は、プロパティ名と値がセットになった連想配列形式の構造化データになっています。
これらのプロパティ項目は、(2)のプロトコル・バッファ・フォーマットにシリアライズされます。このフォーマットは、バイナリ形式の圧縮されたデータとなります。従って、外部からは1個のバイナリ・データとして認識できるだけであり、内部のプロパティ項目の識別などはできないようになってしまいます。
結局、永続化されるキー・バリュー・データは、(2)のようにキーとバイナリ・データだけから構成される単純なデータ・フォーマットになっており、その中のプロパティ項目の数や属性の違いなどは識別不可能になってしまっているわけです。
App Engineのプロトコル・バッファは、データ通信におけるデータ圧縮による通信効率の向上などの目的で、あらゆるクライアント・サーバー間通信で使用されます。上記のように、データ・ストアへの永続化においても有効に使用されています。
図2の(3)で、プロトコル・バッファによってバイナリ形式にシリアライズされたデータは、データ・ストアに永続化されます。しかし、バイナリ形式のデータ・エンティティだけでは、データ検索を行うことができません。
App Engineでは、エンティティか登録(永続化)される時に、同時に複数のキー項目も登録され、これが条件検索用に使われます。キー項目を登録するデータ・ストアもBigtableであり、登録されるキーの種類によって別々のBigtableとなります。
ここまで説明してきたように、App Engineのテーブルでは、エンティティのプロパティ項目を、エンティティ永続化のたびに任意に変更することができます。しかし、このようなエンティティ永続化の柔軟性をJavaで開発したユーザー・プログラムから享受するためには、データ・ストアAPIとしてLow-Level APIを使うことが前提になります。
JDOの場合、第1回で紹介したように、あらかじめデータ・クラスの定義ファイルを作成しておく必要があります。データ・クラスでは、テーブルのプロパティ項目がすべて一意に定義され、この定義と異なるようなプロパティ項目の変更は、一切できません。
このように、JDOは、RDBなどの既存のデータベースを対象として設計されたAPIです。この背景があるため、キー・バリュー型のApp Engineデータ・ストアに対しても、JDOを使う限り、同様の制約を課してしまうことになるわけです。