本記事では、具体的な例を通じてOBKV-HBaseクライアントを使用してデータを処理する方法を紹介します。
前提条件
以下の例を実行する前に、以下の条件を満たしていることを確認してください:
OceanBase Cloudインスタンスがデプロイ済みであること。
MySQL互換テナントが作成済みであること。
データベースが作成済みであること。
OBKV-HBaseデータテーブルが作成済みであること。
この例のテーブルグループ名は
htable1です。各テーブルは1つのカラムファミリに対応しており、必要に応じてテーブルを作成できます。以下のステートメントは、これらのテーブルを作成する方法を示しています。CREATE TABLEGROUP htable1; CREATE TABLE htable1$family1 ( `K` varbinary(1024) NOT NULL, `Q` varbinary(256) NOT NULL, `T` bigint(20) NOT NULL, `V` varbinary(1024) DEFAULT NULL, PRIMARY KEY (`K`, `Q`, `T`) ) TABLEGROUP = htable1 PARTITION BY KEY(`K`) PARTITIONS 3; CREATE TABLE htable1$family2 ( `K` varbinary(1024) NOT NULL, `Q` varbinary(256) NOT NULL, `T` bigint(20) NOT NULL, `V` varbinary(1024) DEFAULT NULL, PRIMARY KEY (`K`, `Q`, `T`) ) TABLEGROUP = htable1 PARTITION BY KEY(`K`) PARTITIONS 3; CREATE TABLE htable1$family3 ( `K` varbinary(1024) NOT NULL, `Q` varbinary(256) NOT NULL, `T` bigint(20) NOT NULL, `V` varbinary(1024) DEFAULT NULL, PRIMARY KEY (`K`, `Q`, `T`) ) TABLEGROUP = htable1 PARTITION BY KEY(`K`) PARTITIONS 3;この記事の例では、OHTableを使用してOBKV-HBaseインスタンスに接続し、データを処理します。OBKV-HBaseクライアントがデプロイおよび設定されており、OHTableを介してインスタンスに接続されていることを確認してください。詳細については、OBKV-HBaseクライアントを使用したインスタンスへの接続を参照してください。
注意事項
- コード例の実行結果は、以下の操作の実行順序によって異なります。結果を再現するには、各操作を順番に実行してください。
- データベースの結果をより直感的に確認するため、この例ではMySQLクライアントを使用してOBKV-HBaseに接続し、SQLでテーブルの状態をクエリします。
注意
OBKV-HBaseのput、delete、get、scanインターフェースは複数のカラムファミリをサポートしています。
Put
注意
HBaseのputパフォーマンスを最適化するには、新バージョンのクライアントとODPを併用してください。ODPのバージョン要件:>= 4.3.0、HBaseクライアントのバージョン要件:>= 1.4.0または>= 2.4.0。
機能説明:
put操作では、1行で複数の列や複数のカラムファミリを指定できます。複数のカラムファミリにまたがる書き込み操作は原子的です。
バージョン(タイムスタンプ)が指定されていない場合、この操作で書き込む各列には、サーバーが操作を実行した際に取得したタイムスタンプがバージョンとして使用されます。複数のカラムファミリにまたがって書き込まれる列は、同じバージョンを使用します。
関数プロトタイプ:
- void put(Put put)
- void put(List
puts)
パラメータ説明:
put:単一レコードを挿入するためのPutオブジェクト。puts:複数のレコードを一括挿入するためのPutオブジェクトの集合。
例:
Put put = new Put("testKey0".getBytes());
put.add("family1".getBytes(), "column1".getBytes(), "value1-1".getBytes());
put.add("family1".getBytes(), "column2".getBytes(), "value1-2".getBytes());
put.add("family2".getBytes(), "column3".getBytes(), "value2-3".getBytes());
put.add("family3".getBytes(), "column4".getBytes(), "value3-4".getBytes());
hTable.put(put);
MySQL [test]> SELECT * FROM htable1$family1;
+----------+---------+----------------+---------+
| K | Q | T | V |
+----------+---------+----------------+---------+
| testKey0 | column1 | -1730184389941 | value1-1|
| testKey0 | column2 | -1730184389941 | value1-2|
+----------+---------+----------------+---------+
2 rows in set
MySQL [test]> SELECT * FROM htable1$family2;
+----------+---------+----------------+---------+
| K | Q | T | V |
+----------+---------+----------------+---------+
| testKey0 | column3 | -1730184389941 | value2-3|
+----------+---------+----------------+---------+
1 row in set
MySQL [test]> SELECT * FROM htable1$family3;
+----------+---------+----------------+---------+
| K | Q | T | V |
+----------+---------+----------------+---------+
| testKey0 | column4 | -1730184389941 | value3-4|
+----------+---------+----------------+---------+
1 row in set
Get
機能説明:
- この関数を呼び出すことで、指定された行のデータを取得できます。
関数プロトタイプ:
- Result get(final Get get)
- Result[] get(List
gets)
パラメータ説明:
get:Getオブジェクト。addColumnまたはaddFamily関数を使用して操作対象を指定します。単一行のget操作では、必要に応じて複数のカラムファミリを組み合わせて操作できます。戻り値はまずK列でソートされ、次にQ列で辞書順にソートされます。addColumn:- 取得する特定の列を指定します。
- カラムファミリと列クエリファイアーを同時に指定する必要があります。
- 特定の列の値を取得するシナリオに適しています。
- 指定された列の値のみを返します。
addFamily:- 取得するカラムファミリ全体を指定します。
- カラムファミリ名のみを指定します。
- 特定のカラムファミリ内のすべての列を取得するシナリオに適しています。
- そのカラムファミリ内のすべての列の値を返します。
gets:Getオブジェクトのリスト。
例:
// Obtain one family.
int maxVersion = 1;
Get get = new Get("testKey0".getBytes());
get.addColumn("family1".getBytes(), "column1".getBytes());
get.addFamily("family2".getBytes());
Result result = hTable.get(get);
for (Cell cell : result.rawCells()) {
System.out.println(new String(CellUtil.cloneRow(cell)) + " "
+ new String(CellUtil.cloneFamily(cell)) + " "
+ new String(CellUtil.cloneQualifier(cell)) + " "
+ new String(CellUtil.cloneValue(cell)));
}
## Output:
## testKey0 family1 column1 value1-1
## testKey0 family2 column3 value2-3
## The preceding Get operation is equivalent to the following SQL queries
MySQL [test]> SELECT * FROM htable1$family1 WHERE k = "testKey0" AND Q = 'column1';
+----------+---------+----------------+---------+
| K | Q | T | V |
+----------+---------+----------------+---------+
| testKey0 | column1 | -1730184389941 | value1-1|
+----------+---------+----------------+---------+
1 row in set
MySQL [test]> SELECT * FROM htable1$family2 WHERE k = "testKey0";
+----------+---------+----------------+---------+
| K | Q | T | V |
+----------+---------+----------------+---------+
| testKey0 | column3 | -1730184389941 | value2-3|
+----------+---------+----------------+---------+
1 row in set
Scan
機能説明:
- この関数を呼び出すことで、指定された条件(
scan/family/qualifier)に基づいてテーブルをスキャンできます。
関数プロトタイプ:
- ResultScanner getScanner(byte[] family, byte[] qualifier)
- ResultScanner getScanner(final byte[] family)
- ResultScanner getScanner(final Scan scan)
パラメータ説明:
family:フィルタリング対象のカラムファミリ。qualifier:フィルタリング対象の列名。scan:Scanオブジェクト。addFamily、addColumnなどのメソッドを使用して操作対象を設定します。addColumn:- 取得する特定の列を指定します。
- カラムファミリと列クエリファイアーを同時に指定する必要があります。
- 特定の列の値を取得するシナリオに適しています。
- 指定された列の値のみを返します。
addFamily:- 取得するカラムファミリ全体を指定します。
- カラムファミリ名のみを指定します。
- 特定のカラムファミリ内のすべての列を取得するシナリオに適しています。
- そのカラムファミリ内のすべての列の値を返します。
例:
Scan scan = new Scan("testKey0".getBytes());
scan.addColumn("family1".getBytes(), "column1".getBytes());
scan.addFamily("family2".getBytes());
scan.setStartRow("testKey0".getBytes());
ResultScanner scanner = hTable.getScanner(scan);
for (Result r : scanner) {
for (Cell cell : r.rawCells()) {
System.out.println(new String(CellUtil.cloneRow(cell)) + " "
+ new String(CellUtil.cloneFamily(cell)) + " "
+ new String(CellUtil.cloneQualifier(cell)) + " "
+ new String(CellUtil.cloneValue(cell)));
}
}
## Output:
## testKey0 family1 column1 value1-1
## testKey0 family2 column3 value2-3
## The preceding Scan operation is equivalent to the following SQL queries
MySQL [test]> SELECT *
-> FROM htable1$family2
-> WHERE K >= "testKey0"
-> UNION
-> SELECT *
-> FROM htable1$family1
-> WHERE K >= "testKey0" AND Q = "column1";
+----------+---------+----------------+---------+
| K | Q | T | V |
+----------+---------+----------------+---------+
| testKey0 | column1 | -1730184389941 | value1-1|
| testKey0 | column3 | -1730184389941 | value2-3|
+----------+---------+----------------+---------+
2 rows in set
OBKV-HBaseは Reverse Scan をサポートしており、RowKeyの逆順(大きい順から小さい順へ)でテーブルデータをスキャンできます。これは通常の順方向スキャン(小さい順から大きい順へ)とは逆です。
注意
V4.4.1以降、Reverse Scanはサブパーティションをサポートし、任意のkey/range `K_PREFIX` パーティションキーと組み合わせてクエリを実行できます。
以下の例は順方向スキャンを示しています:
-- Forward scan
String startKey = "testKey";
String endKey = "testKey9";
String family = "family";
String column = "column";
int maxVersion = 1;
Scan scan = new Scan();
scan.addColumn(family.getBytes(), column.getBytes());
scan.setMaxVersions(maxVersion);
scan.setStartRow(startKey.getBytes());
scan.setStopRow(endKey.getBytes());
ResultScanner scanner = hTable.getScanner(scan);
for (Result r : scanner) {
for (KeyValue kv : r.list()) {
System.out.printf("Scan Demo: Rowkey: %s, Column Family: %s, Column Qualifier: %s, Value: %s, Timestamp: %d%n",
Bytes.toString(r.getRow()),
Bytes.toString(kv.getFamily()),
Bytes.toString(kv.getQualifier()),
Bytes.toString(kv.getValue()),
kv.getTimestamp());
}
}
戻り結果は次のとおりです:
+----------+--------+----------------+----------+
| K | Q | T | V |
+----------+--------+----------------+----------+
| testKey0 | column | -1715961561057 | putValue |
| testKey1 | column | -1715961561132 | putValue |
| testKey2 | column1 | -1715961561132 | putValue |
| testKey2 | column2 | -1715961561132 | putValue |
+----------+--------+----------------+----------+
4 rows in set
以下の例は逆方向スキャンを示しています:
-- Reverse scan
String startKey = "testKey9";
String endKey = "testKey";
String family = "family";
String column = "column";
int maxVersion = 1;
Scan scan = new Scan();
scan.addColumn(family.getBytes(), column.getBytes());
scan.setMaxVersions(maxVersion);
scan.setStartRow(startKey.getBytes());
scan.setStopRow(endKey.getBytes());
// Enable reverse scan
scan.setReversed(true);
ResultScanner scanner = hTable.getScanner(scan);
for (Result r : scanner) {
for (KeyValue kv : r.list()) {
System.out.printf("Scan Demo: Rowkey: %s, Column Family: %s, Column Qualifier: %s, Value: %s, Timestamp: %d%n",
Bytes.toString(r.getRow()),
Bytes.toString(kv.getFamily()),
Bytes.toString(kv.getQualifier()),
Bytes.toString(kv.getValue()),
kv.getTimestamp());
}
}
戻り結果は次のとおりです:
+----------+--------+----------------+----------+
| K | Q | T | V |
+----------+--------+----------------+----------+
| testKey2 | column1 | -1715961561132 | putValue |
| testKey2 | column2 | -1715961561132 | putValue |
| testKey1 | column | -1715961561132 | putValue |
| testKey0 | column | -1715961561057 | putValue |
+----------+--------+----------------+----------+
4 rows in set
カラム値のインクリメント
機能説明:
- この関数を呼び出すと、指定された行の単一の列をインクリメントします。関数が正常に実行されると、その列の新しい値を返します。この列のセルは、64ビット整数を格納するためにlong型である必要があります。
関数プロトタイプ:
- long incrementColumnValue(byte[] row, byte[] family, byte[] qualifier, long amount, boolean writeToWAL)
パラメータ説明:
row:行キー。family:対象のカラムファミリー。テーブル作成時に指定します。qualifier:対象列の名前。amount:インクリメントのステップサイズ。負の数を指定できます。writeToWAL:ログのプリフライトを行うかどうかを指定します。OBKV-HBaseではこのパラメータは不要です。
例:
// 単一の列を1増やします。
String column = "incrementColumn";
String key = "incrementKey";
String family = "family";
long increment_value = 1L;
long ret = hTable.incrementColumnValue(
key.getBytes(),
family.getBytes(),
column.getBytes(),
increment_value);
System.out.printf("Increment Column Demo: ret: %b%n", ret);
MySQL [test]> select *,hex(v) from htable1$family where k = "incrementKey";
+--------------+-----------------+----------------+----------+------------------+
| K | Q | T | V | hex(v) |
+--------------+-----------------+----------------+----------+------------------+
| incrementKey | incrementColumn | -1715961669857 | | 0000000000000001 |
+--------------+-----------------+----------------+----------+------------------+
説明:
- MySQLクライアントを使用してHBaseテーブルを表示する場合、セルのV列に値が表示されないことがあります。この場合、
hex(v)を使用してその値を表示できます。 - カラム値のインクリメント関数がデータベースから条件に合致するセルを検索できない場合、デフォルト値
0を持つセルを生成し、その後インクリメント操作を実行します。
インクリメント
機能の概要:
- この関数を呼び出すと、指定された行の1つまたは複数の列をインクリメントします。対応する列のセルは、64ビット整数を格納するためにlong型である必要があります。
関数のプロトタイプ:
- Result increment(Increment increment)
パラメータの説明:
increment:Incrementオブジェクト。addColumn関数を使用してそのプロパティを指定します。
例:
// 単一の列を1増やします。
String column = "incrementColumn";
String key = "incrementKey";
String family = "family";
long increment_value = 1L;
Increment increment = new Increment(key.getBytes());
increment.addColumn(family.getBytes(), column.getBytes(), increment_value);
Result r = hTable.increment(increment);
for (KeyValue kv : r.list()) {
System.out.printf("Increment Demo: Rowkey: %s, Value:%s%n",
Bytes.toString(r.getRow()),
Bytes.toLong(kv.getValue()));
}
MySQL [test]> select *,hex(v) from htable1$family where k = "incrementKey";
+--------------+-----------------+----------------+----------+------------------+
| K | Q | T | V | hex(v) |
+--------------+-----------------+----------------+----------+------------------+
| incrementKey | incrementColumn | -1715961734681 | | 0000000000000002 |
| incrementKey | incrementColumn | -1715961669857 | | 0000000000000001 |
+--------------+-----------------+----------------+----------+------------------+
説明:
- 同一セルに対してIncrement関数を複数回呼び出すと、複数のバージョンのセルが生成されます。HBaseは更新の意味論をサポートしていないため、セルの変更は新しいバージョンを形成し、クエリ時にバージョンを指定できます。
Append
機能の概要:
- この関数を呼び出すと、指定された行の1つまたは複数の文字型列(例:byteまたはstring)にデータを追加できます。
関数プロトタイプ:
- Result append(Append append)
パラメータ説明:
append:Appendオブジェクト。add関数を使用してそのプロパティを指定します。
例:
String column = "appendColumn";
String key = "appendKey";
String family = "family";
Append append = new Append(key.getBytes());
append.add(family.getBytes(), column.getBytes(), toBytes("_append"));
Result r = hTable.append(append);
for (KeyValue kv : r.list()) {
System.out.printf("Appand Demo: Rowkey: %s, Append Value:%s%n",
Bytes.toString(r.getRow()),
Bytes.toString(kv.getValue()));
}
MySQL [test]> select * from htable1$family where k = "appendKey";
+-----------+--------------+----------------+---------+
| K | Q | T | V |
+-----------+--------------+----------------+---------+
| appendKey | appendColumn | -1715961265748 | _append |
+-----------+--------------+----------------+---------+
説明:
- Append 関数がデータベースから条件に合致するセルを検索できない場合、デフォルト値として空文字列を持つ対応するセルを挿入し、そのセルにデータを追加します。
Delete
機能説明:
- この関数を呼び出すことで、指定されたセルまたは行を削除できます。
関数プロトタイプ:
- void delete(Delete delete)
- void delete(List
deletes)
パラメータ説明:
delete:削除する行のDeleteオブジェクトを指定します。deleteColumn、deleteColumns、またはdeleteFamily関数を使用して設定します。単一行の削除操作では、必要に応じて複数のカラムファミリーを組み合わせて操作できます。deleteColumn:- 特定バージョンの単一列を削除します。
- 列ファミリー、列限定子、およびタイムスタンプを指定する必要があります。
- 特定バージョンのデータを削除する必要があるシナリオに適しています。
deleteColumns:- 指定された列のすべてのバージョンを削除します。
- 列ファミリーと列限定子のみを指定する必要があります。
- 特定の列のすべての履歴データを削除する必要があるシナリオに適しています。
deleteFamily:- 指定された列ファミリー内のすべての列およびすべてのバージョンのデータを削除します。
- 列ファミリー名のみを指定する必要があります。
- 特定の列ファミリーのすべてのデータをクリアする必要があるシナリオに適しています。
例:
// Delete all columns in family1 and column3 in family2.
// A subsequent Get can retrieve only values other than those columns in family1 and family2.
Delete delete = new Delete(toBytes("testKey0"));
delete.deleteFamily("family1".getBytes());
delete.deleteColumns("family2".getBytes(), "column3".getBytes());
hTable.delete(delete);
// Delete all columns for testKey0. A subsequent Get returns no results.
Delete delete = new Delete(toBytes("testKey0"));
hTable.delete(delete);
Exists
機能説明:
- この関数を呼び出すことで、Getオブジェクトで指定されたカラムファミリまたは列が存在するかどうかを判断できます。存在する場合は
trueを返し、存在しない場合はfalseを返します。
関数プロトタイプ:
- boolean exists(Get get)
パラメータ説明:
get:Getオブジェクト。addFamilyまたはaddColumn関数を使用して指定します。
例:
String key = "testKey2";
String family = "family";
Get get = new Get(key.getBytes());
get.addFamily(family.getBytes());
boolean ret = hTable.exists(get);
System.out.printf("Exist Demo: ret: %b%n", ret);
MySQL [test]> select * from htable1$family where k = "testKey2";
+----------+--------+----------------+----------+
| K | Q | T | V |
+----------+--------+----------------+----------+
| testKey2 | column | -1715961561132 | putValue |
+----------+--------+----------------+----------+
説明:
- ExistsのセマンティクスはGetと等価です。
Check And Put
機能説明:
- この関数を呼び出すことで、指定された列のデータをチェックして置き換えることができます。条件を満たし、置き換えに成功した場合は
trueを返し、そうでない場合はfalseを返します。
関数プロトタイプ:
- boolean checkAndPut(byte[] row, byte[] family, byte[] qualifier, byte[] value, Put put)
パラメータ説明:
row:ターゲット行のキー。family:ターゲットのカラムファミリー。qualifier:ターゲット列名。value:ターゲット列の値。put:新しい列値。
例:
String key = "testKey2";
String family = "family";
String column = "column";
String value = "putValue";
String new_value = "value_new";
Put put = new Put(key.getBytes());
put.add(family.getBytes(), column.getBytes(), new_value.getBytes());
boolean ret = hTable.checkAndPut(
key.getBytes(),
family.getBytes(),
column.getBytes(),
value.getBytes(),
put);
System.out.printf("CheckAndPut Demo: ret: %b%n", ret);
MySQL [test]> select * from htable1$family where k = "testKey2";
+----------+--------+----------------+-----------+
| K | Q | T | V |
+----------+--------+----------------+-----------+
| testKey2 | column | -1715961408587 | value_new |
| testKey2 | column | -1715961035471 | putValue |
+----------+--------+----------------+-----------+
説明:
- 主キーが
testKey2、値がputValueのセルを、値がvalue_newの新しいバージョンのセルに変更します。
Check And Delete
機能説明:
- この関数を呼び出すと、マッチ条件を満たす場合に列を削除できます。条件を満たし、削除に成功した場合は
trueを返し、そうでない場合はfalseを返します。
関数プロトタイプ:
- boolean checkAndDelete(byte[] row, byte[] family, byte[] qualifier, byte[] value, Delete delete)
パラメータ説明:
row:マッチする対象行のキー。family:対象のカラムファミリ。テーブル作成時に指定します。qualifier:マッチする対象列名。value:マッチする対象列の値。delete:削除する列。
例:
String key = "testKey2";
String family = "family";
String column = "column";
String value = "value_new";
Delete delete = new Delete(key.getBytes());
delete.deleteColumn(family.getBytes(), column.getBytes());
boolean ret = hTable.checkAndDelete(
key.getBytes(),
family.getBytes(),
column.getBytes(),
value.getBytes(),
delete);
System.out.printf("CheckAndDelete Demo: ret: %b%n", ret);
MySQL [test]> select * from htable1$family where k = "testKey2";
+----------+--------+----------------+----------+
| K | Q | T | V |
+----------+--------+----------------+----------+
| testKey2 | column | -1715961035471 | putValue |
+----------+--------+----------------+----------+
説明:
- 主キーが
testKey2、値がvalue_newのセルが削除され、データベースにはそのセルは存在しなくなります。
Get Configuration
機能説明:
- この関数を呼び出すと、操作インスタンスのconfigハンドルが返され、操作のプロパティを変更できます。
関数プロトタイプ:
- Configuration getConfiguration()
パラメータ説明:
- なし
例:
hTable.getConfiguration().set("rpc.execute.timeout", "1500");