本記事では、具体的な例を用いて、OBKV-HBaseクライアントを使用したデータ処理の方法を説明します。
説明
OBKV-HBaseクライアントがサポートするインターフェースの一覧については、HBase互換インターフェースを参照してください。
前提条件
以下の例を実行する前に、次の準備が完了していることを確認してください。
OceanBaseクラスタがデプロイ済みであること。サポートされているデプロイメントプラン、デプロイメント方法、および詳細なデプロイメント操作については、デプロイメントの概要を参照してください。
MySQLテナントが作成済みであること。テナント作成の詳細な操作については、テナントの作成を参照してください。
データベースが作成済みであること。データベース作成の詳細な操作については、データベースの作成を参照してください。
OBKV-HBaseデータテーブルが作成済みであること。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<Put> 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<Get> gets)
パラメータリスト:
get:getオブジェクト。addColumnまたはaddFamily関数を使用して操作対象を指定する必要があります。単一行のget操作で複数のカラムファミリーを任意に組み合わせて操作できます。戻り値はK列/Q列の辞書順でソートされます。
- addColumn:
- 検索する特定の列を指定するために使用します。
- カラムファミリーと列修飾子を指定する必要があります。
- 特定の列のデータを正確に取得する必要があるシナリオに適しています。
- 指定された列の値のみを返します。
- addFamily:
- 検索するカラムファミリー全体を指定するために使用します。
- カラムファミリーの名前のみを指定する必要があります。
- カラムファミリー内のすべての列のデータを取得する必要があるシナリオに適しています。
- そのカラムファミリー内のすべての列の値を返します。
- addColumn:
gets:getオブジェクトのリスト。getオブジェクトを格納します。
操作例:
// 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)));
}
## 実行結果は次のとおりです
## testKey0 family1 column1 value1-1
## testKey0 family2 column3 value2-3
## 上記のGet操作は、以下のSQLクエリに変換されます
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:
- 検索するカラムファミリー全体を指定するために使用します。
- カラムファミリー名のみを指定する必要があります。
- カラムファミリー内のすべての列のデータを取得するシナリオに適しています。
- そのカラムファミリー内のすべての列の値を返します。
- addColumn:
操作例:
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)));
}
}
## 実行結果は次のとおりです
## testKey0 family1 column1 value1-1
## testKey0 family2 column3 value2-3
## 上記のScan操作は以下のSQLクエリに変換されます
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パーティションキーと組み合わせて複合クエリを実行できます。
昇順スキャンの例は以下のとおりです:
-- 昇順スキャン
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
降順スキャンの例は以下のとおりです:
-- 降順スキャン
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());
// 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
incrementColumnValue
関数の説明:
- テーブルの特定行の単一列値に指定した増加量を加算します。実行が成功した場合、インクリメント後の値を返します。指定された列のセルはlong型(64ビット整数型)である必要があります。
関数プロトタイプ:
long incrementColumnValue(byte[] row, byte[] family, byte[] qualifier, long amount, boolean writeToWAL)
パラメータリスト:
- row:行キー。
- family:対象カラムファミリー。ここではテーブル作成時に指定したカラムファミリーです。
- qualifier:対象列名。
- amount:増加量(負の値も可能)。
- writeToWAL:先行書き込みログ(WAL)に書き込むかどうか。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) を使用して表示することができます。
- 上記のように、Incrementの動作は、データベースで条件を満たすセルが見つからない場合、デフォルト値0を持つセルを生成し、その後Incrementを行うことです。
increment
関数の説明:
- 指定された行の単一列または複数列の値に指定した増加量を加算します。指定する列のセルはlong型(64ビット整数型)でなければなりません。
関数のプロトタイプ:
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 |
+--------------+-----------------+----------------+----------+------------------+
備考:
- 上記のように、1つのCellに対して複数回加算を行うと、複数のバージョンのCellが生成されます。HBaseにはUpdate操作がないため、1つのCellに対する変更はマルチバージョンになります。ユーザーはクエリを実行する際にバージョンを指定できます。
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の動作は、データベース内で条件を満たすCellが検索されない場合、対応するCellを挿入し、値はデフォルトで空文字列となります。その後、生成されたレコードに対してAppend操作を実行します。
delete
関数の説明:
- 指定されたセル(cells)または行(rows)を削除します。
関数のプロトタイプ:
void delete(Delete delete)void delete(List<Delete> deletes)
パラメータリスト:
- delete:Deleteオブジェクト。ここでは、削除する行を指します。deleteColumn、deleteColumns、deleteFamily関数で設定します。単一行のDelete操作で、複数のカラムファミリーを任意に組み合わせて操作できます。
- deleteColumn:
- 特定バージョンの単一列を削除するために使用します。
- カラムファミリー、列修飾子、およびタイムスタンプを指定する必要があります。
- 特定バージョンのデータを削除するシナリオに適しています。
- deleteColumns:
- 列のすべてのバージョンを削除するために使用します。
- カラムファミリーと列修飾子のみを指定する必要があります。
- 特定の列のすべての履歴データを削除するシナリオに適しています。
- deleteFamily:
- 指定されたカラムファミリー内のすべての列とそのすべてのバージョンのデータを削除するために使用します。
- カラムファミリーの名前のみを指定する必要があります。
- 特定のカラムファミリーのすべてのデータをクリアするシナリオに適しています。
- deleteColumn:
操作例:
// family1のすべての列とfamily2のcolumn3列を削除します。
// この時点で再度Getを実行すると、family1とfamily2のcolumn3列以外の値のみが取得されます。
Delete delete = new Delete(toBytes("testKey0"));
delete.deleteFamily("family1".getBytes());
delete.deleteColumns("family2".getBytes(), "column3".getBytes());
hTable.delete(delete);
// testKey0のすべての列を削除します。この時点で再度Getを実行しても結果は取得できません。
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 |
+----------+--------+----------------+----------+
備考:
- ExistのセマンティクスはGetと同じです。
checkAndPut
関数の説明:
- 指定された列データをチェックして置き換えます。条件が満たされ、置き換えに成功した場合は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のCellを変更し、value_newの値を持つ新しいバージョンのCellを生成します。
checkAndDelete
関数説明:
- 削除する列をマッチングし、マッチ条件に合致して削除が成功した場合は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のCellは削除されており、データベース内にこのCellは存在しません。
getConfiguration
関数説明:
- 操作インスタンス内のconfigハンドルを返し、操作中にプロパティを変更するために使用できます。
関数プロトタイプ:
Configuration getConfiguration()
パラメータリスト:
- なし
操作例:
hTable.getConfiguration().set("rpc.execute.timeout", "1500");