読み取り

このページでは、Bigtable に送信できる読み取りリクエストの種類と、パフォーマンスへの影響について説明し、特定の種類のクエリに関する推奨事項を示します。このページを読む前に、Bigtable の概要を理解する必要があります。

概要

Bigtable への読み取りリクエストは、リクエストされた行の内容をキー順にストリーミング バックします。つまり、行の内容は保存されている順序で返されます。レスポンスを返した書き込みを読み取ることができます。

テーブルがサポートするクエリは、ユースケースに最適な読み取りのタイプを決定する際に有用です。Bigtable の読み取りリクエストは、次の 2 つの一般カテゴリに分類されます。

  • 単一行の読み取り
  • スキャン、または複数行の読み取り

読み取りは行レベルでアトミックに処理されます。つまり、行の読み取りリクエストを送信すると、Bigtable は行全体を返すか、リクエストが失敗した場合は行を返しません。行の一部は、明示的にリクエストしない限り返されません。

API を直接呼び出すのではなく、Cloud Bigtable クライアント ライブラリを使用してテーブルからデータを読み取ることを強くおすすめします。読み取りリクエストを送信する方法を示すコードサンプルは、複数の言語でご利用いただけます。すべての読み取りリクエストは ReadRows API 呼び出しを行います。

Data Boost サーバーレス コンピューティングを使用したデータの読み取り

Bigtable Data Boost を使用すると、毎日のアプリケーション トラフィックに影響を与えることなく、バッチ読み取りジョブとクエリを実行できます。Data Boost は、コア アプリケーションがクラスタのノードをコンピューティングに使用している間に、Bigtable データの読み取りに使用できるサーバーレス コンピューティング サービスです。

Data Boost はスキャンに最適ですが、単一行の読み取りにはおすすめしません。Data Boost を逆スキャンに使用することはできません。詳細と利用条件については、Data Boost の概要をご覧ください。

単一行の読み取り

行キーに基づいて単一行をリクエストできます。単一行読み取り(ポイント読み取りとも呼ばれます)は、Data Boost と互換性がありません。コードサンプルは次のバリエーションでご利用いただけます。

スキャン

スキャンは、Bigtable データを読み取る最も一般的な方法です。行キー接頭辞を指定するか、行キーの先頭と末尾を指定することで、Bigtable から連続する行の範囲または複数の行の範囲を読み取ることができます。コードサンプルは次のバリエーションでご利用いただけます。

リバース スキャン

リバース スキャンでは、行キー接頭辞または行の範囲を指定して、行の範囲を逆方向に読み取ることができます。行キー接頭辞は、逆方向に読み取るスキャンの開始点として使用されます。行の範囲を指定すると、終了行キーがスキャンの開始点として使用されます。

逆順でのスキャンは次のような場合に便利です。

リバース スキャンは、フォワード スキャンよりも効率的ではありません。通常は、ほとんどのスキャンが転送されるように行キーを設計します。50 行以下の短いスキャンの場合は、リバース スキャンを使用して、低レイテンシの応答時間を維持します。

逆方向にスキャンするには、ReadRowsRequest フィールドの reversed の値を true に設定します。デフォルト値は false です。

次のクライアント ライブラリを使用するときにリバース スキャンを使用できます。

  • C++ バージョン 2.18.0 以降の Bigtable クライアント ライブラリ
  • Go バージョン 1.21.0 以降の Bigtable クライアント ライブラリ
  • Java バージョン 2.24.1 以降の Bigtable クライアント ライブラリ
  • Java バージョン 2.10.0 以降の Bigtable HBase クライアント ライブラリ

リバース スキャンの使用方法を示すコードサンプルについては、逆方向にスキャンするをご覧ください。

ユースケースの例

次の例は、リバース スキャンを使用して、顧客が最後にパスワードを変更したときと、特定の日前後の製品の価格変動を見つける方法を示しています。

パスワードの再設定

行キーのそれぞれにお客様 ID と日付が 123ABC#2022-05-02 形式で含まれており、列の 1 つがパスワードがリセットされた時刻を格納する password_reset であると仮定します。Bigtable では、以下のようにデータが自動的に辞書順で保存されます。パスワードが再設定されていなかった場合、この列は行(日数)に存在しません。

`123ABC#2022-02-12,password_reset:03`
`123ABC#2022-04-02,password_reset:11`
`123ABC#2022-04-14`
`123ABC#2022-05-02`
`223ABC#2022-05-22`

顧客 123ABC が最後にパスワードを再設定した時間を確認する場合は、今日の日付または将来の日付を使用して、123ABC#123ABC#<DATE> の範囲を逆順にスキャンし、行の上限が 1 で列 password_reset を含むすべての行を取得します。

価格の変更

この例では、行キーに商品、モデル、タイムスタンプの値が含まれ、列の 1 つには特定の時点での商品とモデルの料金が含まれています。

`productA#model2#1675604471,price:82.63`
`productA#model2#1676219411,price:82.97`
`productA#model2#1677681011,price:83.15`
`productA#model2#1680786011,price:83.99`
`productA#model2#1682452238,price:83.12`

2023 年 2 月 14 日の価格を基準とした価格の変動を確認するには(特定の日付の行キーがテーブルに存在しない場合も)、行キー productA#model2#1676376000 から N 行分のスキャンを行い、同じ行から同じ行数のリバース スキャンを行います。この 2 つのスキャンにより、指定された時間の前後の料金がわかります。

フィルタ後の読み取り

特定の値を格納する行または行の一部のみが必要な場合は、読み取りリクエストでフィルタを使用できます。フィルタを使用すると、必要なデータを詳細に選択できます。

また、フィルタを使用すると、テーブルが使用しているガベージ コレクション ポリシーに読み取りが一致するようにできます。これは、タイムスタンプ付きの新しいセルを既存の列に頻繁に書き込む場合に特に有用です。ガベージ コレクションでは期限切れとなったデータが削除されるまでに最大 1 週間かかるため、タイムスタンプの範囲フィルタを使用してデータを読み取ることで、必要以上にデータが読み取られることを防止できます。

フィルタの概要では、使用できるフィルタの種類について詳しく説明しています。フィルタの使用では複数の言語で例を示しています。

承認済みビューからデータを読み取る

承認済みビューからデータを読み取るには、次のいずれかを使用する必要があります。

  • gcloud CLI
  • Java 用 Bigtable クライアント

他の Bigtable クライアント ライブラリでは、表示権限はまだサポートされていません。

Bigtable Data API の ReadRows メソッドまたは SampleRowKeys メソッドを呼び出すメソッドはすべてサポートされています。クライアントの作成時に、テーブルの ID に加えて承認済みビューの ID を指定します。

継続的マテリアライズド ビューからデータを読み取る

SQL または ReadRows Data API 呼び出しを使用して、継続的マテリアライズド ビューからデータを読み取ることができます。継続的マテリアライズド ビューは読み取り専用です。マテリアライズド ビューのデータは、定義するクエリに基づいて型指定されます。

SQL

SQL を使用して継続的マテリアライズド ビューからデータを読み取るには、Bigtable Studio クエリ エディタまたは SQL クエリをサポートするクライアント ライブラリのいずれかを使用します。

SQL はクエリ結果を型付きの列として自動的に公開するため、クエリでエンコードを処理する必要はありません。

継続的マテリアライズド ビューを作成すると、Bigtable は、ビューの構造化された行キーを定義するテーブルの行キー スキーマを自動的に作成します。SQL を使用した構造化行キーのクエリの詳細については、構造化行キーのクエリをご覧ください。

Data API

Bigtable 用のクライアント ライブラリの ReadRows 呼び出しを使用して継続的マテリアライズド ビューから読み取る場合は、ビューの定義に使用される SQL クエリを確認する必要があります。ビューに _key 列が定義されているかどうか(ReadRows を使用して読み取るビューに推奨)、_timestamp 列があるかどうかを確認します。

また、各列の型を把握し、アプリケーション コードで列データをデコードする必要があります。

継続的マテリアライズド ビューの集計値は、ビュー定義の列の出力タイプに基づいて、次の表で説明するエンコードを使用して保存されます。

エンコード
BOOL 1 バイトの値。1 = true、0 = false
BYTES エンコードなし
INT64(または INT、SMALLINT、INTEGER、BIGINT、TINYINT、BYTEINT) 64 ビットのビッグ エンディアン
FLOAT64 64 ビット IEEE 754(NaN と +/-inf を除く)
STRING UTF-8
TIME/TIMESTAMP Unix エポックからのマイクロ秒数を表す 64 ビット整数(GoogleSQL と一致)
詳細については、Data API リファレンスの エンコードをご覧ください。

ビュー内の各列の型を把握するだけでなく、列ファミリーと列修飾子も把握する必要があります。デフォルトの列ファミリーは default と呼ばれ、列修飾子は定義クエリで指定されたエイリアスです。たとえば、次のクエリで定義された継続的マテリアライズド ビューについて考えてみましょう。

SELECT
  _key,
  SUM(clicks) AS sum_clicks
FROM
  mytable
GROUP BY
  sum_clicks

ReadRows を使用してビューをクエリする場合は、列ファミリー default と列修飾子 sum_clicks を指定します。

読み取りとパフォーマンス

フィルタを使用する読み取りは、フィルタなしの読み取りよりも実行速度が低下し、CPU 使用率が増大します。一方、返されるデータの量を制限することで、使用するネットワーク帯域幅の量を大幅に削減できます。 一般に、フィルタはレイテンシではなくスループット効率を制御するために使用します。

読み取りパフォーマンスを最適化するには、次の方法を検討してください。

  1. 行セットを可能な限り制限します。ノードがスキャンしなければならない行数を制限することは、最初のバイトまでの時間と全体的なクエリ レイテンシを改善するための最初のステップです。行セットを制限しない場合、Bigtable はほぼ確実にテーブル全体をスキャンする必要があります。そのため、最もよく使用されるクエリがこのように機能するようスキーマを設計することをおすすめします。

  2. 行セットを制限した後にパフォーマンスをさらに調整するには、基本フィルタの追加を試みます。列のセットまたは返されるバージョンの数を制限すると、一般にレイテンシは増大せず、場合によっては Bigtable は各行の過去の無関係なデータを効率的にシークできます。

  3. 最初の 2 つの方法を実施した後でさらに読み取りパフォーマンスを調整する場合は、より複雑なフィルタの使用を検討してください。これを試すことについては、次のような理由が考えられます。

    • 依然として不要なデータが大量に返される。
    • クエリを Bigtable に push することで、アプリケーション コードを簡素化する必要があります。

    ただし、大きな値に対して条件、インターリーブ、正規表現一致を必要とするフィルタには、スキャン対象データのほとんどを一致結果として返す場合にメリットよりもデメリットが多くなる傾向が見られる点に留意してください。この問題は、クライアント側で大幅な節約には至らずに、クラスタの CPU 使用率が増加するという形で発生します。

これらの方法に加えて、1 つの読み取りリクエストで、多数の連続していない行キーや行範囲を読み取ることは避けてください。1 つのリクエストで何百もの行キーや行範囲をリクエストすると、Bigtable はテーブルをスキャンして、リクエストされた行を順番に読み取ります。この並列性の欠如が全体的なレイテンシに影響を与え、ホットノードが読み取られると、テール レイテンシの増加につながる場合があります。リクエストされた行の範囲が増えるほど、読み取りの完了に時間がかかります。このレイテンシが許容できない場合は、代わりに、取得する行範囲を小さくした同時リクエストを複数送信する必要があります。

一般に、1 つのリクエストでより多くの行範囲を読み取ると、スループットは最適化されますが、レイテンシはされません。複数の同時リクエストで小さい行範囲を読み取ると、レイテンシは最適化されますが、スループットはされません。レイテンシとスループットの適切なバランスを図ることは、アプリケーションの要件によって異なります。また、同時読み込みリクエストの数と 1 つのリクエストでの行範囲の数を調整することで、このバランスを取ることができます。

大きな行

Bigtable では、大きな行に適用される次の制限が適用されます。

  • 行の最大サイズは 256 MB です。上限を超えた行を読み取る必要がある場合は、リクエストをページ分割して、cells per row limit フィルタcells per row offset フィルタを使用します。ページ分割された読み取りリクエストの間に書き込みが開始された場合、読み取りはアトミックに実行されない可能性があります。

  • ReadRows API 呼び出しの最大サイズは 512 KB です。上限を超えると、Bigtable は INVALID_ARGUMENT エラーを返します。

次のステップ