さくらVPSでApache Cassandra 0.7のSecondary indexesを利用してみる



Cassandra 0.7で実装されたSecondary indexesを試してみた。「cassandra-cli」上で動作するかまずは試してみる。
参考にしたのは、「DataStax:What's new in Cassandra 0.7: Secondary indexes」と「λab's Blog:Cassandra0.7.0のSecondary indexesを使用したJava APIサンプル」を参考にしました。

テスト用のkeyspaceを作成する

まずは、テスト用の「keyspace」と「column family」を作成する。

create keyspace test2;
 
use test2;
 
create column family users with comparator=UTF8Type and column_metadata=[{column_name:full_name, validation_class:UTF8Type},{column_name:birth_date, validation_class:LongType, index_type:KEYS}];

「column_name:birth_date」で「index_type:KEYS」と指定しています。*1
 

テストデータを作成する

テストデータを投入する為のプログラムを作成。
テストデータは、2件用意した。

No full_name birth_date
1 takahashimaiko 1985
2 yamamotoyuuki 1987

 
「batch_mutate」メソッドで二件挿入した。 
 

// カラムファミリ名
String cfName = "users";

// key と カラムファミリの Map の Map を作成
Map<ByteBuffer, Map<String, List<Mutation>>> mutaionMap = new HashMap<ByteBuffer, Map<String, List<Mutation>>>();

// レコードを挿入
long timestamp = System.currentTimeMillis();

long birthday1 = 1985;
long birthday2 = 1987;

// 登録・更新したい値から Mutation オブジェクトの List を作成
List<Mutation> columns = new ArrayList<Mutation>();
columns.add(toMutation("full_name", "takahashimaiko", timestamp));
columns.add(toMutation("birth_date", FBUtilities.toByteBuffer(birthday1), timestamp));

List<Mutation> columns2 = new ArrayList<Mutation>();
columns2.add(toMutation("full_name", "yamamotoyuuki", timestamp));
columns2.add(toMutation("birth_date", FBUtilities.toByteBuffer(birthday2), timestamp));

// カラムファミリと Mutation のリストの Map を作成
Map<String, List<Mutation>> innerMap = new HashMap<String, List<Mutation>>();
Map<String, List<Mutation>> innerMap2 = new HashMap<String, List<Mutation>>();

innerMap.put(cfName, columns);
innerMap2.put(cfName, columns2);

// 取り合えず同じ内容を key だけ別にして追加。
mutaionMap.put(ByteBuffer.wrap("takahashimaiko".getBytes("UTF-8")), innerMap);
mutaionMap.put(ByteBuffer.wrap("yamamotoyuuki".getBytes("UTF-8")), innerMap2);

client.batch_mutate(mutaionMap, ConsistencyLevel.ONE);

showData(client);

port.close();
 
/**
 * カラム名、値、タイムスタンプ値 から Mutation オブジェクトを生成する。
 * @param name
 * @param value
 * @param timestamp
 * @return
 * @throws UnsupportedEncodingException
 */
public static Mutation toMutation(final String name, final String value, final long timestamp) throws UnsupportedEncodingException {
	

System.out.printf("カラム名:[%s] 値:[%s] タイムスタンプ:[%s]",
		name,
		value,
		timestamp);
System.out.println(" ");

Mutation mutation = new Mutation();
ColumnOrSuperColumn csc = new ColumnOrSuperColumn();
csc.setColumn(new Column(ByteBuffer.wrap(name.getBytes("UTF-8")), ByteBuffer.wrap(value.getBytes("UTF-8")), timestamp));
mutation.setColumn_or_supercolumn(csc);
return mutation;
}

/**
 * カラム名、値、タイムスタンプ値 から Mutation オブジェクトを生成する。
 * @param name
 * @param value
 * @param timestamp
 * @return
 * @throws UnsupportedEncodingException
 */
public static Mutation toMutation(final String name, final ByteBuffer value, final long timestamp) throws UnsupportedEncodingException {
System.out.printf("カラム名:[%s] 値:[%s] タイムスタンプ:[%s]",
		name,
		value,
		timestamp);
System.out.println(" ");

Mutation mutation = new Mutation();
ColumnOrSuperColumn csc = new ColumnOrSuperColumn();
csc.setColumn(new Column(ByteBuffer.wrap(name.getBytes("UTF-8")), value, timestamp));
mutation.setColumn_or_supercolumn(csc);
return mutation;
}

 
念のため、挿入したテストデータを確認する。
 

[default@test2] list users;
Using default limit of 100
-------------------
RowKey: yamamotoyuuki
=> (column=birth_date, value=1987, timestamp=1295249913049)
=> (column=blood, value=B, timestamp=1295249913049)
=> (column=full_name, value=yamamotoyuuki, timestamp=1295249913049)
-------------------
RowKey: takahashimaiko
=> (column=birth_date, value=1985, timestamp=1295249913049)
=> (column=blood, value=A, timestamp=1295249913049)
=> (column=full_name, value=takahashimaiko, timestamp=1295249913049)

2 Rows Returned.

 

where句を試してみる

「birth_date」が「1985」のデータを取得する。

[default@test2] get users where birth_date = 1985;
-------------------
RowKey: takahashimaiko
=> (column=birth_date, value=1985, timestamp=1295249913049)
=> (column=blood, value=A, timestamp=1295249913049)
=> (column=full_name, value=takahashimaiko, timestamp=1295249913049)

1 Row Returned.

 

動的にセカンダリインデックス追加

下記の通り、動的にセカンダリインデックス追加。

update column family users with comparator=UTF8Type and column_metadata=[{column_name:full_name, validation_class:UTF8Type},{column_name:birth_date, validation_class:LongType, index_type:KEYS},{column_name:blood, validation_class:UTF8Type, index_type:KEYS}];

「column_name:blood」を増やしたので、テストデータを再度追加する。

下記の形でアクセスすることができた。

[default@test2] get users where blood = 'A';
-------------------
RowKey: takahashimaiko
=> (column=birth_date, value=1985, timestamp=1295249913049)
=> (column=blood, value=A, timestamp=1295249913049)
=> (column=full_name, value=takahashimaiko, timestamp=1295249913049)

1 Row Returned.

とりあえず、参考ページと同じことを確認することができました。
 


 

*1: index_typeにどんなものがあるか不明