TsurugiのTsubakuro(Java通信ライブラリー)のKvsClientのメモ。
Tsurugiサーバーの内部はKVS(Key Value Store)でデータを管理している。
TsurugiのSQL実行エンジンは、SQL文を「KVSアクセスする処理」に変換して実行する。
Tsubakuroでは(SQLを介さずに)KVSアクセスすることが出来る。
(元々は、JavaからKVSアクセスする機能は予定に入っておらず、C++でKVSアクセスする処理を書けるようになる予定だった)
KVSアクセスではput/get/remove/scanなど、テーブル単位での読み書きの機能しか無い。
SQLより単純だが、その分速いはず。
TsubakuroでKVSアクセスするにはKvsClientクラスを使用する。
ただし、Tsurugi 1.0.0-BETA1ではまだ正式公開されておらず、限定的な機能しか使用できない。
(なお、Tsurugiサーバーのバージョン付けとTsubakuro(クライアント)のバージョンは一致していない)
KvsClientはtsubakuro-kvsにあるので、biuld.gradleのdependenciesに追加する必要がある。
dependencies { def tsubakuroVersion = '1.0.1' implementation "com.tsurugidb.tsubakuro:tsubakuro-session:${tsubakuroVersion}" implementation "com.tsurugidb.tsubakuro:tsubakuro-connector:${tsubakuroVersion}" implementation "com.tsurugidb.tsubakuro:tsubakuro-kvs:${tsubakuroVersion}" }
SqlClient | KvsClient | |
---|---|---|
トランザクションの開始方法 | SqlClientからTransactionを生成する。 | KvsClientからTransactionHandleを生成する。 |
処理の実行方法 | TransactionのメソッドでSQLを実行する。 | KvsClientのメソッドでKVSアクセス処理を実行する。 その際にTransactionHandleを引数で渡す。 |
KvsClientインスタンスはSessionをアタッチして生成する。
import com.tsurugidb.tsubakuro.kvs.KvsClient;
try (var kvsClient = KvsClient.attach(session)) { 〜 }
KvsClientはクローズする必要があるが、クローズしてもアタッチされたSessionはクローズされない。
import com.tsurugidb.tsubakuro.kvs.TransactionHandle; import com.tsurugidb.tsubakuro.kvs.TransactionOption;
try (var kvsClient = KvsClient.attach(session)) { // トランザクション開始 TransactionOption option = TransactionOption.forShortTransaction().build(); try (TransactionHandle transactionHandle = kvsClient.beginTransaction(option).await(3, TimeUnit.SECONDS)) { 〜 // コミット kvsClient.commit(transactionHandle).await(10, TimeUnit.SECONDS); } }
メソッド | 説明 | 例 |
---|---|---|
attach | SessionをアタッチしてKvsClientインスタンスを生成する。 | try (var kvsClient = KvsClient.attach(session)) { |
beginTransaction | トランザクションを開始する。(TransactionHandleを生成する) | try (FutureResponse<TransactionHandle> future = kvsClient.beginTransaction(transactionOption)) { |
commit | トランザクションをコミットする。 | try (FutureResponse<Void> future = kvsClient.commit(transactionHandle)) { |
try (FutureResponse<Void> future = kvsClient.commit(transactionHandle, commitType)) { |
||
rollback | トランザクションをロールバックする。 | try (FutureResponse<Void> future = kvsClient.rollback(transactionHandle)) { |
get | キーを指定してテーブルから1行取得する。 →getの例 |
try (FutureResponse<GetResult> future = kvsClient.get(transactionHandle, tableName, key)) { |
put | テーブルに1行書き込む。 putType省略時はOVERWRITEと同じ。 →putの例 |
try (FutureResponse<PutResult> future = kvsClient.put(transactionHandle, tableName, record, putType)) { |
remove | キーを指定してテーブルから1行削除する。 removeType省略時はCOUNTINGと同じ。 →removeの例 |
try (FutureResponse<RemoveResult> future = kvsClient.remove(transactionHandle, tableName, key, removeType)) { |
scan | テーブルから複数行取得する。 Tsurugi 1.0.0-BETA1では未実装。 |
|
batch | 複数のKVS操作をまとめて実行する。 Tsurugi 1.0.0-BETA1では未実装。 |
getやremoveメソッドにおける「キー」は、基本的にプライマリキー。
ただしインデックスが作られているテーブルでは、インデックスも指定できるようになるらしい?
KvsClientのputメソッドは、テーブルに1行書き込む。
import com.tsurugidb.tsubakuro.kvs.PutResult; import com.tsurugidb.tsubakuro.kvs.PutType; import com.tsurugidb.tsubakuro.kvs.RecordBuffer;
var record = new RecordBuffer(); record.add("pk", 1); // int record.add("value", 456L); // bigint PutResult result = kvsClient.put(transactionHandle, "test", record, PutType.OVERWRITE).await(3, TimeUnit.SECONDS); System.out.printf("put.size=%d%n", result.size());
RecordBufferでテーブルの1行分のデータを設定する。(全カラムのデータが必須)
それをテーブル名と共にputメソッドに渡す。
putメソッドの引数PutTypeの意味は以下の通り。
PutType | 説明 | 備考 |
---|---|---|
OVERWRITE (デフォルト) |
テーブルにレコードが存在していたら更新し、無かったら追加する。 | SQLのinsert or replace相当 |
IF_ABSENT | テーブルにレコードが存在しない場合だけ追加する。(存在する場合は何もしない) | SQLのinsert相当 |
IF_PRESENT | テーブルにレコードが存在する場合に更新する。(存在しない場合は何もしない) | SQLのupdate相当 |
putでは、SQLのinsert文と異なり、プライマリキーの一意制約違反が発生することは無い。
putメソッドの実行結果として、PutResultが返る。
PutResultにはsizeメソッドがあり、実際に書き込んだ件数が返る。
KvsClientのgetメソッドは、キーを指定してテーブルから1行取得する。
import com.tsurugidb.tsubakuro.kvs.GetResult; import com.tsurugidb.tsubakuro.kvs.Record; import com.tsurugidb.tsubakuro.kvs.RecordBuffer;
var key = new RecordBuffer(); key.add("pk", 1); GetResult result = kvsClient.get(transactionHandle, "test", key).await(3, TimeUnit.SECONDS); if (result.isSingle()) { Record record = result.asRecord(); int pk = record.getInt("pk"); Long value = record.isNull("value") ? null : record.getLong("value"); System.out.printf("%d, %d%n", pk, value); } else { System.out.println("get nothing"); }
RecordBufferでテーブルのキーのデータを設定する。(複合キーの場合、それら全てのデータが必須)
それをテーブル名と共にgetメソッドに渡す。
getメソッドの実行結果として、GetResultが返る。
指定したキーのデータがあったかどうかはGetResultのisSingleメソッドで判別できる。
trueの場合、GetResultのasRecordメソッドで1レコード分のデータが取得できる。
KvsClientのremoveメソッドは、キーを指定してテーブルから1行削除する。
import com.tsurugidb.tsubakuro.kvs.RecordBuffer; import com.tsurugidb.tsubakuro.kvs.RemoveResult; import com.tsurugidb.tsubakuro.kvs.RemoveType;
var key = new RecordBuffer(); key.add("pk", 1); RemoveResult result = kvsClient.remove(transactionHandle, "test", key, RemoveType.COUNTING).await(3, TimeUnit.SECONDS); System.out.printf("remove.size=%d%n", result.size());
RecordBufferでテーブルのキーのデータを設定する。(複合キーの場合、それら全てのデータが必須)
それをテーブル名と共にremoveメソッドに渡す。
removeメソッドの引数RemoveTypeの意味は以下の通り。
RemoveType | 説明 |
---|---|
COUNTING (デフォルト) |
実際に削除した件数を返す。(RemoveResultのsizeメソッド) |
INSTANT | 削除件数を返さない。(RemoveResultのsizeメソッドは常に1を返す) 削除対象が存在したかどうかのチェックを行わない分、速いのだと思われる。 |
removeメソッドの実行結果として、RemoveResultが返る。
RemoveTypeがCOUNTINGの場合、RemoveResultのsizeメソッドで実際に削除した件数が分かる。(と言っても、キーを指定するので、削除件数は1か0のどちらかだろう)
RemoveTypeがINSTANTの場合は、RemoveResultのsizeメソッドは常に1を返す。