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

ApsaraDB for HBase:Rowkey の設計方法

最終更新日:Mar 29, 2026

Rowkey は、HBase テーブル内の各行の一意の識別子です。データの格納方法、パーティション分割方法、およびアクセス方法を制御します。大規模にデータを書き込む前に、Rowkey を慎重に設計してください。

このトピックでは、ログデータとトランザクションデータのトレードオフと例を含む、5つの設計上の考慮事項について説明します。

Rowkey の仕組み

クエリメソッド

HBase は2つのクエリメソッドをサポートしており、それぞれRowkey の設計に異なる制約があります。

メソッド説明制約
GET完全な Rowkey で単一の行をルックアップします。Rowkey を構成するすべてのフィールドが既知である必要があります。
Scan開始キーと終了キーの間の行の範囲を読み取ります。プレフィックスベースの範囲のみがサポートされます。

スキャンにおけるプレフィックス制約: スキャンは、特定のプレフィックスで始まる行と一致しますが、サフィックスでクエリしたり、Rowkey の中央の値と一致させたりすることはできません。たとえば、Rowkey が辞書語である場合、スキャンは pre で始まるすべての単語を見つけることができますが、ing で終わる単語を見つけることはできません。

プレフィックススキャンとして表現できないクエリの場合は、次のいずれかのアプローチを使用してください。

  • 逆キー構造を持つインデックステーブルを作成します。

  • 不要な行を破棄するためにサーバー側フィルターを適用します。

  • セカンダリインデックスを使用します。

Rowkey の一意性とバージョン

同じ Rowkey を持つ行は、複数のバージョンを持つ単一のレコードとして扱われます。デフォルトでは、GET は最新バージョンを返します。意図的に Multi-Version Concurrency Control (MVCC) を使用しない限り、Rowkey は一意である必要があります。

Rowkey はデータベースのプライマリキーのように使用してください。単一のフィールドまたは複数のフィールドの複合にすることができます。

  • [user_id] — ユーザーごとに1つのレコード

  • [user_id][order_id] — ユーザーごとに複数のレコード

設計上の考慮事項

データ分散: ホットスポットの回避

HBase は、Rowkey の範囲 (辞書式順序) に従ってリージョンサーバー全体にデータを分散します。多くの書き込みが共通プレフィックス (たとえば、2024-01-01T00:00:01 のようなタイムスタンプ優先キー) を共有する場合、すべての書き込みが同じリージョンサーバーに着地します。これにより、書き込みスループットを低下させ、他のサーバーをアイドル状態にするホットスポットが作成されます。

書き込みをリージョンサーバー全体に分散するには、次のいずれかの手法を使用してください。

ハッシュプレフィックスによるソルト化

MD5 ハッシュの最初の数文字を Rowkey の先頭に追加します。ハッシュは決定論的であるため、同じ入力は常に同じプレフィックスにマッピングされ、読み取りは効率的です。

[md5(user_id).subStr(0, 4)][user_id][order_id]

トレードオフ: 同じユーザーの行は異なるリージョンに分散されます。単一ユーザーの範囲をスキャンするには、複数のターゲットGET またはフィルター付きスキャンが必要です。

キーの反転

カーディナリティの高いプレフィックスフィールドを反転します。たとえば、時間とともに増分するユーザー ID を反転すると、先頭バイトがランダム化されます。

[reverse(user_id)][order_id]

トレードオフ: 自然な順序が失われるため、反転されたフィールドでの範囲スキャンは意味がありません。

剰余演算によるバケット化

剰余演算を使用して各行をバケットに割り当て、バケット番号を先頭に追加します。これは、タイムスタンプが単調増加する時系列データに効果的です。

long bucket = timestamp % numBuckets;
[bucket][timestamp][hostname][log_event]

トレードオフ: 特定の時間範囲のすべてのデータを取得するには、すべての numBuckets 範囲をスキャンし、結果をマージする必要があります。

ランダムサフィックスの追加

複数の行に書き込みを分散するために、乱数を追加します。

[user_id][order_id][random(100)]

トレードオフ: 特定のレコードを読み取るには、ランダムサフィックスを知る必要があります。インデックスなしではポイントルックアップは非実用的です。

選択方法: 分散された行全体をスキャンする必要がある場合 (個々のレコードをルックアップするだけでなく)、ランダムサフィックスではなくハッシュ化を使用してください。ハッシュ化は決定論的であるため、読み取りを効率的にルーティングできます。

Rowkey の長さ: 短く保つ

Rowkey は、HBase のすべての列値とともに格納されます。長い Rowkey は、すべての行のすべての列でストレージオーバーヘッドを増大させます。Rowkey は可能な限り短く保ってください。

  • 文字列を数値型に置き換えます。 long は8バイトを占有し、文字列 "2015122410" は10バイト、MD5 文字列は32バイトを占有します。"2015122410" の代わりに Long(2015122410) を使用してください。

  • 完全な名前の代わりにコードを使用します。 たとえば、"Taobao" の代わりに tb を使用してください。

フィールド境界の明確さ: 部分一致の防止

Rowkey がデリミタなしで複数のフィールドを結合する場合、スキャン範囲は余分な行を返す可能性があります。たとえば、Rowkey が [column1][column2][column3] で、host1 から host2 までスキャンすると、行 host12... もその範囲に含まれます。

これを防ぐには、2つのアプローチがあります。

固定長パディング: 各フィールドを固定幅にパディングして、境界を曖昧さのないものにします。

[rpad(column1, 'x', 20)][column2]

デリミタ: デリミタ文字でフィールドを区切ります。

[column1][_][column2]

固定長パディングはスキャンに効率的です。デリミタは読みやすいです。

降順: タイムスタンプの反転を使用

デフォルトでは、HBase スキャンは昇順キー順で行を返します。最新のエントリを最初に取得する必要がある場合は、2つのオプションがあります。

オプション1: リバーススキャン API (scan.setReverse(true))

実装は簡単ですが、リバーススキャンはフォワードスキャンよりもパフォーマンスが低いです。降順が時折の要件である場合に使用してください。

オプション2: 行キー内のタイムスタンプの反転

生のタイムスタンプの代わりに Long.MAX_VALUE - timestamp を格納します。これにより、自然なソート順が反転され、新しいエントリがフォワードスキャンで最初に表示されます。

timestamp = Long.MAX_VALUE - timestamp;
[hostname][log_event][timestamp]

降順が主要なアクセスパターンであり、スキャンパフォーマンスが重大である場合に使用してください。

設計例

適切な Rowkey の設計は、主要なアクセスパターンによって異なります。同じデータセットでも、クエリ方法によって異なる設計が必要になる場合があります。以下の例は、アクセスパターンが設計決定をどのように推進するかを示しています。

ログデータと時系列データ

データ要素は、hostnamelog_eventtimestamp です。

アクセスパターンRowkey の設計備考
時間範囲でホストのメトリックをクエリ[hostname][log_event][timestamp]ホストごとの範囲スキャンに効率的です。単一のホストが書き込みを支配する場合、ホットスポットを作成する可能性があります。
ホストの最新レコードをクエリ[hostname][log_event][Long.MAX_VALUE - timestamp]タイムスタンプの反転により、フォワードスキャンで最新のエントリが最初に配置されます。
時間全体に書き込みを均等に分散 (大量のデータまたは支配的なホストなし)[バケット][タイムスタンプ][ホスト名][ログイベント] ただし、バケット = タイムスタンプ mod numBuckets時間範囲の結果を集計するには、すべてのバケット範囲をスキャンする必要があります。

選択方法: ホストごとの範囲クエリが主要なユースケースである場合は、[hostname][log_event][timestamp] から開始してください。書き込みホットスポットが出現したり、時間範囲クエリが多くのホストにまたがる場合は、バケットパターンに切り替えてください。

トランザクションデータ

トランザクションには、買い手、売り手、注文番号の3つのロールが関与します。異なるアクセスパターンには異なる Rowkey の設計が必要であり、多くの場合、複数のテーブルが必要です。

アクセスパターンテーブルRowkey の設計
時間範囲で売り手の注文をクエリSeller table[seller_id][timestamp][order_number]
時間範囲で買い手の注文をクエリBuyer table[buyer_id][timestamp][order_number]
注文番号で注文をルックアップIndex table[order_number]

3つのアクセスパターンすべてをカバーするように3つのテーブルすべてを設計してください。インデックステーブルを使用して order_number をルックアップし、その値で買い手または売り手テーブルをクエリしてください。

次のステップ

  • HBase データモデルの概要

  • HBase のセカンダリインデックス

  • HBase テーブルのパフォーマンスチューニング