LindormTable を使用すると、HBase シェルまたは ApsaraDB for HBase API for Java で作成された HBase テーブルで、データ移行なしで直接 SQL クエリを実行できます。カラムマッピングは、スキーマフリーな HBase ストレージモデルと Lindorm SQL を橋渡しすることで、標準的な SQL 構文を使用して既存のデータをフィルタリング、インデックス作成、クエリできます。
前提条件
ワイドテーブルエンジンのバージョンが 2.6.4 以降であること。現在のバージョンの確認方法またはアップグレード方法については、「LindormTable リリースノート」および「Lindorm インスタンスのマイナーエンジンバージョンのアップグレード」をご参照ください。
背景情報
Lindorm ワイドテーブルエンジンは、Lindorm シェルまたは HBase Java API を使用して作成されたデータテーブルに直接アクセスできます。ただし、HBase はスキーマフリーであるため、HBase のカラムは VARBINARY (Byte) 型の動的カラムとして扱われます。動的カラムの詳細については、「動的カラム」をご参照ください。HBase API を通じて書き込まれたカラムで Lindorm SQL を使用して豊富なデータ型やセカンダリインデックスを活用できるよう、ApsaraDB for HBase は HBase カラムマッピングおよび HBase 互換型を提供しています。
構文
Lindorm SQL では、HBase テーブルのカスタムカラムファミリー内のクオリファイアにマッピングを追加することで、SQL クエリが容易になります。
マッピングの追加および削除の構文は次のとおりです。
dynamic_column_mapping_statement := ALTER TABLE table_name MAP DYNAMIC COLUMN
qualifier_definition hbase_type;
dynamic_column_unmapping_statement := ALTER TABLE table_name UNMAP DYNAMIC COLUMN
qualifier_definition_list;
qualifier_definition_list := qualifier_definition
(',' qualifier_definition)*
qualifier_definition := [ family_name ':' ] qualifier_name
hbase_type := HLONG | HINTEGER | HSHORT | HFLOAT |
HDOUBLE | HSTRING | HBOOLEAN次の表は、hbase_type で指定できるマッピングデータ型を説明しています。
データ型 | 対応する Java 型 | 説明 |
HLONG | java.lang.Long | Bytes.toBytes(long) メソッドを使用して HBase カラムを書き込みます。 |
HINTEGER | java.lang.Integer | Bytes.toBytes(int) メソッドを使用して HBase カラムを書き込みます。 |
HSHORT | java.lang.Short | Bytes.toBytes(short) メソッドを使用して HBase カラムを書き込みます。 |
HFLOAT | java.lang.Float | Bytes.toBytes(float) メソッドを使用して HBase カラムを書き込みます。 |
HDOUBLE | java.lang.Double | Bytes.toBytes(double) メソッドを使用して HBase カラムを書き込みます。 |
HSTRING | java.lang.String | Bytes.toBytes(String) メソッドを使用して HBase カラムを書き込みます。 |
HBOOLEAN | java.lang.Boolean | Bytes.toBytes(boolean) メソッドを使用して HBase カラムを書き込みます。 |
ワイドテーブルエンジン バージョン 2.5.1 以降では、ロウキーのマッピングをサポートしています。マッピング方法は他のクオリファイアと同じです。マッピング対象は ROW とし、ROW キーワードはバッククォート () で囲む必要があります。
他の言語を使用する場合は、Java クラス org.apache.hadoop.hbase.util.Bytes の toBytes メソッドを参照して、書き込み前にデータをエンコードしてください。
Java の Bytes.toBytes(String) は UTF-8 エンコーディングを使用します。他の言語で toBytes を使用して String を Bytes に変換する場合も、UTF-8 エンコーディングが必要です。
事前準備
次の例では、HBase Java API を使用します。詳細については、「ApsaraDB for HBase API for Java を使用したアプリケーションの開発」をご参照ください。
テーブルの作成とデータの書き込みに関するその他の方法については、「Lindorm シェルを使用した LindormTable への接続」をご参照ください。
// カラムファミリー "f1" を持つ HBase サンプルテーブル "dt" を作成
try (Admin admin = connection.getAdmin()) {
HTableDescriptor htd = new HTableDescriptor(TableName.valueOf("dt"));
htd.addFamily(new HColumnDescriptor(Bytes.toBytes("f1")));
admin.createTable(htd);
}
// データを書き込む
try (Table table = connection.getTable(TableName.valueOf("dt"))) {
byte[] rowkey = Bytes.toBytes("row1");
byte[] family = Bytes.toBytes("f1");
Put put = new Put(rowkey);
// カラム "name" に String 値を書き込みます
String name = "Some one";
put.addColumn(family, Bytes.toBytes("name"), Bytes.toBytes(name));
// カラム "age" に Int 値を書き込みます
int age = 25;
put.addColumn(family, Bytes.toBytes("age"), Bytes.toBytes(age));
// カラム "time" に Long 値を書き込みます
long timestamp = 1656675491000L;
put.addColumn(family, Bytes.toBytes("time"), Bytes.toBytes(timestamp));
// カラム "buycode" に Short 値を書き込みます
short buycode = 123;
put.addColumn(family, Bytes.toBytes("buycode"), Bytes.toBytes(buycode));
// カラム "price" に Float 値を書き込みます
float price = 12.3f;
put.addColumn(family, Bytes.toBytes("price"), Bytes.toBytes(price));
// カラム "price2" に Double 値を書き込みます
double price2 = 12.33333;
put.addColumn(family, Bytes.toBytes("price2"), Bytes.toBytes(price2));
// カラム "isMale" に Boolean 値を書き込みます
boolean isMale = true;
put.addColumn(family, Bytes.toBytes("isMale"), Bytes.toBytes(isMale));
// null 値を書き込む場合。すべての型で、null の書き込みは次のように表されます。
//put.addColumn(family, qualifier, null);
table.put(put);
}操作手順
次の例では、サンプルテーブル dt を使用して、SQL を使用して HBase テーブルにアクセスする方法を説明します。
Lindorm-cli を使用してワイドテーブルエンジンに接続します。詳細については、「Lindorm-cli を使用したワイドテーブルエンジンへの接続と使用」をご参照ください。
説明SQL を使用して ApsaraDB for HBase Enhanced Edition の HBase テーブルにアクセスする場合、コンソールで取得したアドレスを
jdbc:lindorm:table:url=http://コンソールで取得した Java API アドレスの形式で構成します。 ポートを 30020 から 30060 に変更します。例えば、コンソールで取得した接続文字列アドレスが
ld-bp1ietqp4fby3****-proxy-hbaseue.hbaseue.rds.aliyuncs.com:30020の場合、変換後の接続文字列アドレスはjdbc:lindorm:table:url=http://ld-bp1ietqp4fby3****-proxy-hbaseue.hbaseue.rds.aliyuncs.com:30060になります。ALTER TABLEステートメントを使用して、dt テーブルに書き込まれたデータにカラムマッピングを追加します。ALTER TABLE dt MAP DYNAMIC COLUMN `ROW` HSTRING, f1:name HSTRING, f1:age HINTEGER, f1:time HLONG, f1:buycode HSHORT, f1:price HFLOAT, f1:price2 HDOUBLE, f1:isMale HBOOLEAN;説明カラムマッピングを追加すると、データが書き込まれているかどうかに関係なく、カラムのデータ型が指定されます。
システムはスキーマに基づいて Bytes から元の値をデコードします。したがって、Lindorm SQL にマッピングする際には、正しいデータ型を使用する必要があります。
次の例では、f:age2 カラムのデータ型を HINTEGER として指定すると、システムは Bytes.toInt() メソッドを呼び出し、誤った元の値を返します。
int age = 25; byte[] ageValue = Bytes.toBytes(age); put.addColumn(Bytes.toBytes("f"), Bytes.toBytes("age"), ageValue);// カラム f:age のデータ型は INT であり、Lindorm SQL では HINTEGER にマッピングされます。 String age2 = "25"; byte[] age2Value = Bytes.toBytes(age2); put.addColumn(Bytes.toBytes("f"), Bytes.toBytes("age2"), age2Value);// カラム f:age2 のデータ型は STRING であり、Lindorm SQL では HSTRING にマッピングされます。DESCRIBE ステートメントを使用して、現在のスキーマのマッピング関係を確認します。
DESCRIBE dt;説明DESCRIBE TABLE 構文の詳細については、「DESCRIBE/SHOW/USE」をご参照ください。
SQL ステートメントを使用して dt テーブルのデータをクエリします。
SELECT * FROM dt LIMIT 1; SELECT * FROM dt WHERE f1:isMale=true LIMIT 1; SELECT * FROM dt WHERE f1:name='Some one' LIMIT 1; SELECT * FROM dt WHERE f1:time>1656675490000 and f1:time<1656675492000 LIMIT 1;(オプション) セカンダリインデックスの作成
セカンダリインデックスは、ストレージ容量と引き換えに時間を短縮します。プライマリキー以外のクエリパターンのクエリ効率を向上させますが、一部のストレージ容量を占有します。セカンダリインデックスの構文および使用制限の詳細については、「CREATE INDEX」および「セカンダリインデックス」をご参照ください。
プライマリテーブル dt のプロパティを変更します。
ALTER TABLE dt SET 'MUTABILITY' = 'MUTABLE_LATEST';説明カスタムタイムスタンプを使用する場合は、プライマリテーブルのプロパティを MUTABLE_ALL に設定してください。
セカンダリインデックスを作成します。
CREATE INDEX idx ON dt(f1:age) WITH (INDEX_COVERED_TYPE ='COVERED_DYNAMIC_COLUMNS');オプション: ワイドテーブルエンジンのバージョンが 2.6.3 より前で、セカンダリインデックスの作成時に async パラメータ (非同期インデックス構築) を使用した場合は、プライマリテーブルの履歴データをインデックステーブルに手動で構築してください。構築が完了すると、セカンダリインデックスを使用して履歴データをクエリできます。作成時に async パラメータを使用しなかった場合は、この手順をスキップできます。
BUILD INDEX idx ON dt;インデックスを確認します。
SHOW INDEX FROM dt;結果:
+---------------+----------- -+-------------+--------------+------------------+---------------+-----------------+----------------+-------------+ | TABLE_SCHEMA | DATA_TABLE | INDEX_NAME | INDEX_STATE | INDEX_PROGRESS | INDEX_TYPE | INDEX_COVERED | INDEX_COLUMN | INDEX_TTL | +---------------+-------------+-------------+--------------+------------------+---------------+-----------------+----------------+-------------+ | default | dt | idx | ACTIVE | 100% | SECONDARY | TRUE | f1:age,ROW | | +---------------+-------------+-------------+--------------+------------------+---------------+-----------------+----------------+-------------+説明戻り値の INDEX_STATE が Active の場合、データ構築が完了したことを示します。
戻り値の INDEX_PROGRESS は、インデックス構築の進行状況を示します。
オプション: EXPLAIN ステートメントを使用して実行計画を確認し、セカンダリインデックスがヒットしているかどうかを確認します。
EXPLAIN SELECT * FROM dt WHERE f1:age=23 LIMIT 1;
オプション: 検索インデックスの作成
検索インデックスを作成します。
CREATE INDEX search_idx USING SEARCH ON dt(f1:age,f1:name);説明SQL を使用して HBase テーブルに検索インデックスを作成する場合、各検索インデックスカラムには次の制限があります。
すべての検索インデックスカラムは、カラムマッピングで定義されている必要があります。
サポートされているデータ型は、マッピング可能なデータ型と一致しています。詳細については、「マッピングデータ型」をご参照ください。
検索インデックスカラムのマッピングを削除することはできません。削除すると、クエリ結果が不正確になります。
カスタムタイムスタンプを使用して HBase テーブルに書き込み、検索インデックスを作成する必要がある場合は、テーブルの MUTABILITY プロパティを
MUTABLE_ALLに設定する必要があります。
インデックスが正常に作成されたかどうかを確認します。
SHOW INDEX FROM dt;結果:
+--------------+------------+------------+-------------+----------------+------------+---------------+----------------+-----------+-------------------+ | TABLE_SCHEMA | DATA_TABLE | INDEX_NAME | INDEX_STATE | INDEX_PROGRESS | INDEX_TYPE | INDEX_COVERED | INDEX_COLUMN | INDEX_TTL | INDEX_DESCRIPTION | +--------------+------------+------------+-------------+----------------+------------+---------------+----------------+-----------+-------------------+ | default | dt | idx | ACTIVE | DONE | SECONDARY | DYNAMIC | f1:age,ROW | | | | default | dt | search_idx | BUILDING | N/A | SEARCH | NA | f1:age,f1:name | 0 | | +--------------+------------+------------+-------------+----------------+------------+---------------+----------------+-----------+-------------------+
オプション: カラムマッピングの削除
カラムマッピングを削除します。次に例を示します。
ALTER TABLE dt UNMAP DYNAMIC COLUMN f1:isMale;複数のカラムマッピングを削除します。次に例を示します。
ALTER TABLE dt UNMAP DYNAMIC COLUMN f1:price, f1:price2;