すべてのプロダクト
Search
ドキュメントセンター

Lindorm:SQL を使用した HBase テーブルへのアクセス

最終更新日:Mar 28, 2026

LindormTable を使用すると、データの書き込み方法を変更することなく、既存の HBase テーブルを SQL でクエリできます。カラム修飾子を型付き SQL カラムにマップし、SELECT クエリを実行したり、セカンダリインデックスおよび検索インデックスを作成したりできます。

前提条件

開始する前に、以下の条件を満たしていることを確認してください。

カラムマッピングの仕組み

HBase テーブルはスキーマレスです。カラムには生のバイト列(VARBINARY)が格納され、カラム名は動的です。LindormTable のカラムマッピング機能はこのギャップを埋めます:各修飾子の書き込み時に使用される Java シリアル化型を宣言すると、Lindorm SQL がバイト列をデコードし、カラムを型付き SQL カラムとして公開します。これにより、WHERE フィルター、セカンダリインデックス、および HBase データに対する検索インデックスが可能になります。

動的カラムの詳細については、「動的カラム」をご参照ください。

カラムマッピング構文

ALTER TABLE を使用して、カラムマッピングを追加または削除します。

-- マッピングを追加
ALTER TABLE <table_name> MAP DYNAMIC COLUMN [<family>:]<qualifier> <hbase_type>;

-- 1 つ以上のマッピングを削除
ALTER TABLE <table_name> UNMAP DYNAMIC COLUMN [<family>:]<qualifier> [, ...];

サポートされる hbase_type の値

Java 型関数の作成使用タイミング
HLONGjava.lang.LongBytes.toBytes(long)Java long
HINTEGERjava.lang.IntegerBytes.toBytes(int)Java int
HSHORTjava.lang.ShortBytes.toBytes(short)Java short
HFLOATjava.lang.FloatBytes.toBytes(float)Java float
HDOUBLEjava.lang.DoubleBytes.toBytes(double)Java double
HSTRINGjava.lang.StringBytes.toBytes(String) — UTF-8Java String
HBOOLEANjava.lang.BooleanBytes.toBytes(boolean)Java boolean
重要

マッピング型は、書き込み時に使用された Java シリアル化メソッドと完全に一致させる必要があります。不一致があると、Lindorm SQL が誤ったバイト列を読み取り、不正な結果を返す可能性があります。詳しくは、下記の「よくあるミス」をご参照ください。

使用上の注意点

  • マッピングを追加すると、対象カラムの型が宣言されます。ただし、そのカラムに既にデータが存在する必要はありません。

  • 行キーのマッピングは LindormTable 2.5.1 以降でサポートされています。行キー識別子はバックティックで囲んでください: ROW

  • Java 以外の言語では、toBytes メソッドを org.apache.hadoop.hbase.util.Bytes から使用してください。文字列は常に UTF-8 でエンコードされます。

よくあるミス

マッピング型と書き込みパスが一致しない

これは最も重大な正確性リスクです。f:age カラムが Bytes.toBytes(int) で書き込まれている場合、マッピングは HINTEGER とする必要があります。誤って HSTRING としてマッピングすると、Lindorm SQL は 4 バイトの整数データに対して Bytes.toString() を呼び出し、無意味な出力を返します。

正しいマッピングの例を以下に示します。

int age = 25;
put.addColumn(Bytes.toBytes("f"), Bytes.toBytes("age"), Bytes.toBytes(age));
// HINTEGER としてマッピング

String age2 = "25";
put.addColumn(Bytes.toBytes("f"), Bytes.toBytes("age2"), Bytes.toBytes(age2));
// HSTRING としてマッピング

これらの混同は、クエリ結果が不正になる最も一般的な原因です。

サンプルデータの準備

以下の手順では、次の HBase テーブルおよびデータを使用します。すでに HBase テーブルをお持ちの場合は、「カラム修飾子のマッピング」に進んでください。

サンプルでは、カラムファミリー f1 を持つテーブル dt を作成し、ApsaraDB for HBase Java API を使用して 1 行のデータを書き込みます。HBase Shell を使用する場合は、「Lindorm Shell を使用した LindormTable への接続」をご参照ください。

// カラムファミリー f1 を持つテーブル dt を作成
try (Admin admin = connection.getAdmin()) {
    HTableDescriptor htd = new HTableDescriptor(TableName.valueOf("dt"));
    htd.addFamily(new HColumnDescriptor(Bytes.toBytes("f1")));
    admin.createTable(htd);
}

// 1 行を書き込み
try (Table table = connection.getTable(TableName.valueOf("dt"))) {
    byte[] rowkey = Bytes.toBytes("row1");
    byte[] family = Bytes.toBytes("f1");
    Put put = new Put(rowkey);

    String name = "Some one";
    put.addColumn(family, Bytes.toBytes("name"), Bytes.toBytes(name));       // HSTRING

    int age = 25;
    put.addColumn(family, Bytes.toBytes("age"), Bytes.toBytes(age));         // HINTEGER

    long timestamp = 1656675491000L;
    put.addColumn(family, Bytes.toBytes("time"), Bytes.toBytes(timestamp));  // HLONG

    short buycode = 123;
    put.addColumn(family, Bytes.toBytes("buycode"), Bytes.toBytes(buycode)); // HSHORT

    float price = 12.3f;
    put.addColumn(family, Bytes.toBytes("price"), Bytes.toBytes(price));     // HFLOAT

    double price2 = 12.33333;
    put.addColumn(family, Bytes.toBytes("price2"), Bytes.toBytes(price2));   // HDOUBLE

    boolean isMale = true;
    put.addColumn(family, Bytes.toBytes("isMale"), Bytes.toBytes(isMale));   // HBOOLEAN

    table.put(put);
}

カラム修飾子のマッピング

  1. Lindorm-cli を使用して LindormTable に接続します。手順については、「Lindorm-cli を使用した LindormTable への接続および利用」をご参照ください。

    ApsaraDB for HBase Performance-enhanced Edition の HBase テーブルにアクセスする場合、Java API の URL 形式を jdbc:lindorm:table:url=http://<API URL for Java> に変更し、ポートを 30020 から 30060 に変更してください。たとえば、ld-bp1ietqp4fby3****-proxy-hbaseue.hbaseue.rds.aliyuncs.com:30020jdbc:lindorm:table:url=http://ld-bp1ietqp4fby3****-proxy-hbaseue.hbaseue.rds.aliyuncs.com:30060 に変更します。
  2. 行キーおよびすべての修飾子を対応する Lindorm SQL 型にマップします。

    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;
  3. DESCRIBE コマンドを実行してマッピングを確認します。

    DESCRIBE dt;

    DESCRIBE 構文の詳細については、「DESCRIBE/SHOW/USE」をご参照ください。

  4. テーブルをクエリします。

    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;

インデックスの作成(任意)

インデックスを追加するとクエリパフォーマンスが向上しますが、追加のストレージが必要になります。クエリパターンに応じてインデックスの種類を選択してください。

インデックスの種類推奨用途トレードオフ
セカンダリインデックス標準的な書き込み量におけるプライマリキー以外のカラムに対するクエリ読み取り速度の向上、ストレージの増加、書き込み時のわずかなオーバーヘッド
検索インデックス全文検索または複雑な多条件クエリ柔軟なクエリ、より高いストレージコスト

セカンダリインデックスの作成

  1. テーブルの MUTABILITY 属性を設定します。

    カスタムタイムスタンプでデータを書き込む場合は、MUTABLE_ALL を使用し、MUTABLE_LATEST は使用しないでください。
    ALTER TABLE dt SET 'MUTABILITY' = 'MUTABLE_LATEST';
  2. インデックスを作成します。

    CREATE INDEX idx ON dt(f1:age) WITH (INDEX_COVERED_TYPE ='COVERED_DYNAMIC_COLUMNS');
  3. `async` パラメーターを指定し、かつ LindormTable のバージョンが 2.6.3 より前の場合、既存データをインデックステーブルにビルドします。

    BUILD INDEX idx ON dt;

    この手順は、async を使用しなかった場合にスキップしてください。

  4. インデックスを確認します。

    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_STATEACTIVE のとき、インデックスは利用可能になります。INDEX_PROGRESS はビルドの進行状況を示します。

  5. (任意)クエリでセカンダリインデックスが使用されているかを確認します。

    EXPLAIN SELECT * FROM dt WHERE f1:age=23 LIMIT 1;

    詳細については、「CREATE INDEX」および「セカンダリインデックス」をご参照ください。

検索インデックスの作成

  1. 検索インデックスを作成します。

    CREATE INDEX search_idx USING SEARCH ON dt(f1:age, f1:name);

    HBase テーブル上で検索インデックスを作成する前に、以下の点にご注意ください。

    • 検索インデックスに含めるすべてのカラムについて、あらかじめカラムマッピングが定義済みである必要があります。

    • カラムのデータ型は、「カラムマッピング構文」でリストされているサポート対象のマッピング型と一致している必要があります。

    • 検索インデックスを作成した後は、カラムマッピングを削除しないでください。削除すると、クエリ結果が不正になる可能性があります。

    • カスタムタイムスタンプでデータを書き込む場合は、インデックス作成前に MUTABILITYMUTABLE_ALL に設定してください。

  2. インデックスのステータスを確認します。

    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;

1 つのステートメントで複数のマッピングを削除する場合:

ALTER TABLE dt UNMAP DYNAMIC COLUMN f1:price, f1:price2;

次のステップ