キーのみのレコードの使用
キーのみの索引ビュー・レコードは、キー内のレコードの情報をすべて伝達します。レコードのデータ部分は空の値に設定されます。この方式では、各索引ビュー・レコードはセカンダリ・キーとキーが参照するプライマリ・レコード・キーとの1つの組合せを表します。Oracle NoSQL Databaseはレコードの大規模化に適しているため、これにより前の項で説明したスケーラビリティの問題が解消されます。
注意:
次の例では、かなり長いキー・パスを使用しています。これはわかりやすさのためです。ただし、通常はキー・パスは短い方が望ましいため、ここに示すパスはレコードのキーの作成方法としてお薦めするものではありません。
基本的に、キーのみの索引ビュー・レコードは、キー・パスのメジャー部分で索引ビューのキーを、キー・パスのマイナー部分でプライマリ・レコードのキーを伝達します。つまり、次のようになります。
/Secondary/Key/Path/-/Primary/Key/Path
ここで、マイナー・パス・コンポーネントはプライマリ・レコードのキー・パスです。たとえば、前の項に示した例に基づくと、次のようになります。
/Secondary/Key/Path/-/Corporate/people/10012
レコードのメジャー・キー・パス部分は詳細情報を伝達する必要があります。
-
索引キーの接頭辞
これは、レコードが索引ビュー・レコードであることを示すために使用される接頭辞値です。ストア内で一意であるかぎり、接頭辞は
IDX
など、どのようなものでもかまいません。 -
索引名
これは、この索引ビューを他のタイプの索引ビューと区別するために使用されます。このレコードで索引付けされる情報を示す単純な名前(
EMPLOYEE_NAME
、EMPLOYEE_LOCATION
など)を使用できます。ただし、コードを正しく設定した場合、さらに複雑な情報を伝達することもできます。これは、「複雑な索引名」で詳しく説明します。 -
フィールド値
メジャー・キー・パスの残りの部分は、関連するプライマリ・レコードから取得された一連の1つ以上のフィールド値です。これは、索引付けする実際の情報です。
最も単純な例では、キーのこの部分には1つのフィールド値のみが含まれます。たとえば、すべての従業員に組織で索引付けする場合は、組織名になります。次に例を示します。
/IDX/ORGANIZATION/Engineering/-/Corporate/people/10012
これは、従業員レコード10012がエンジニアリング組織に属していることを示すビュー・エントリです。
ただし、キー・パスのこの部分には複数のフィールド値を含めることができます。この場合、複数列のビューになります。この例としては、従業員の共通の名前と姓による索引付けがあります。どちらもプライマリ・レコードでは個別のフィールドになります。
/IDX/EMP_NAME/Smith/Robert/-/Corporate/people/10012 /IDX/EMP_NAME/Smith/Patricia/-/Corporate/people/40288 /IDX/EMP_NAME/Smyth/Don/-/Corporate/people/7893
複雑な索引名
前述のように、特に索引付け要件が単純な場合、索引名は単純なテキスト・ラベルにできます。ただし、索引名でビュー・レコードに関する詳細情報を伝達することもできます。次のものを識別できるように索引名を作成できます。
-
プライマリ・レコードで使用されるAvroスキーマ名。
-
このビューが索引付けしているフィールド名のリスト。特に、索引付けしているフィールドの数が増えたり索引ビューのタイプの数が増えてくると、この情報は、Avroバインディング・コードを一般化するのに役立ちます。
この情報を伝達する索引名を作成するには、索引名に必要なすべての情報を保持するリスト・オブジェクトを作成した後、java.security.MessageDigest
を使用して情報の一方向ハッシュを作成するという方法があります。リストのバイト配列への変換は、Key.createKey()
メソッドを使用して実行できます。次に例を示します。
/**
* Construct and return an index name representing an index type.
*/
private String getIndexName(String schemaName,
List<String> indexFieldNames) {
MessageDigest md = null;
try {
/*
* The implementation for digestCache is omitted
* for brevity.
*/
md = digestCache.get();
List<String> minorPath = new ArrayList<String>();
minorPath.add(schemaName);
minorPath.addAll(indexFieldNames);
byte[] bytes =
Key.createKey("", minorPath).toString().getBytes();
md.update(bytes);
return new String(md.digest());
} finally {
digestCache.free(md);
}
}
これは、索引名で伝達する情報は一方向ハッシュでロックされることを意味します。その情報をハッシュから取得する方法はないため、ある場所に保存する必要があります。索引ビュー・メタデータを記録するには、個別のレコード・セットが必要です。
索引ビュー・メタデータの管理
索引ビュー・メタデータは、各索引タイプについて記録する情報です。通常、これは索引名の作成に使用する情報です(複雑な索引名を使用する場合)。索引の状態をメタデータの一部として記録することもできます。
索引ビュー・メタデータを一連のキーのみのレコードとして収集できます。この場合、キーは次のように作成されます。
/PREFIX/INDEX_NAME/-/SCHEMA_NAME/FNAME1/FNAME2/.../STATE
それぞれの意味は次のとおりです。
-
PREFIX
は、このレコードが索引ビュー・メタデータ・レコードであることを示すために使用する一意の識別子です。たとえば、META
などです。 -
INDEX_NAME
は、メタデータを収集する索引のタイプに使用する名前です。単純な名前(ORGANIZATION
、EMP_NAME
など)を使用している場合は、その名前を使用します。前の項で説明したような、ハッシュ化された複雑な名前を使用している場合は、その名前をここで使用します。 -
SCHEMA_NAME
は、プライマリ・レコードで使用されるAvroスキーマの名前です。これは、複雑な索引名の作成に使用したのと同じスキーマ名である必要があります。 -
FNAME1
、FNAME2
などは、このビュー・タイプが使用しているプライマリ・レコードのフィールド名です。これらの名前も、複雑な索引名の作成に使用したフィールド名と同じである必要があります。また、索引ビュー・レコード・キーの作成に使用したフィールド値と同じ順序で表示される必要があります。 -
STATE
は、このメタデータ・レコードで表される索引タイプの現在の状態です。ビューSTATE
の例は、次のとおりです。-
BUILDING
は、索引ビューが現在作成中であることを示します。 -
DELETING
は、索引ビューが現在削除中であることを示します。 -
READY
は、索引ビューを使用する準備ができたことを示します。
これらは提案にすぎません。
STATE
は、コードに役立つ情報を示すことができます。ただし、ここに示した例では、コードがビューを使用するのは状態がREADY
の場合のみです。 -
索引ビュー・レコードとメタデータの併用
すべてをまとめて複雑な索引名を使用する索引ビューを作成するには、次の手順を実行します。
-
作業しているスキーマ名とフィールド名を使用して索引名を作成します。
-
前の項で説明したようにメタデータ・レコードを作成し、状態を
BUILDING
に設定します。 -
使用するストアについてこの手順を繰り返し、索引付けするプライマリ・レコードごとにビュー・レコードを作成します。ビュー・レコードのメジャー・キー・パスの一部として、ステップ1で作成した索引名を使用します。詳細は、「キーのみのレコードの使用」および「複雑な索引名」を参照してください。
-
ビューの作成が完了したら、メタデータ・レコードのステータスを
READY
に変更します(そのためには、古いレコードを削除して新しいレコードを作成します)。
索引ビューを使用する(読み取る)には、次の手順を実行します。
-
対応するメタデータ・レコードを確認し、索引ビューが
READY
状態であることを確認します。そうでない場合は、読取りを中止するか、状態がREADY
に変わるまで一時停止できます。 -
検索する索引ビュー・レコードについてこの手順を繰り返します。
-
そのようなレコードごとに、そのレコードを使用して対応するプライマリ・レコードを取得します。
-
プライマリ・レコードごとに、対応するメタデータ・レコードに含まれるスキーマ名とフィールド名をAvroバインディングとともに使用して、プライマリ・レコードのデータをシリアライズ/デシリアライズします。
既存のレコードを更新するには、次の手順を実行します。
-
プライマリ・レコードを取得します。
-
索引ビュー・レコードを取得します。
-
必要に応じてプライマリ・レコードを変更します。
-
変更がプライマリ・レコードに反映されるように索引ビュー・レコードを変更します。
-
索引ビューのステータスを確認して、READY状態であることを確認します。そうである場合は、索引ビュー・レコードをストアに書き戻します。
索引ビューのステータスがREADYではない場合は、索引ビュー・レコードを書き込む前にステータスがREADYに変わるまで待機するか、操作を中断します。
-
変更したプライマリ・レコードをストアに書き戻します。
これらの操作をすべて実行する例は、Oracle NoSQL Databaseディストリビューションに含まれています。詳細は、「例」を参照してください。
キーのサイズに関する考慮事項
キーが長くなるほど、ノードで使用するメモリーが増えます。したがって、キャッシュ内に十分なレコードを保持できないため、キーはシステムの読取り/書込みスループット全体に損害を与えるほど大きくなる可能性があります。
ここで説明するキーのみの設計パターンでは、キーが非常に長くなる可能性が高いです。キー・サイズが非常に大きいためにパフォーマンスの問題が発生するかどうかは、キーが実際に存在する期間、管理する必要があるキーの数、およびノードで使用可能なメモリーの量に依存します。
キーが非常に大きいためにI/Oスループットの問題が発生する場合は、他の設計方法を実装する必要があります。