Bigtable 用 GoogleSQL のクエリの例

このページの例では、一般的な Bigtable クエリと高度な Bigtable クエリの SQL クエリパターンを示します。Google SQL クエリは、Bigtable Studio クエリエディタで実行できます。Java 用 Bigtable クライアント ライブラリを使用してクエリを実行することもできます。

このページを読む前に、Bigtable 用の GoogleSQL の概要をご覧ください。

このページの例では、サンプル用のデータと同様の ID と値を使用します。

一般的な Bigtable SQL クエリパターン

Bigtable データに対する一般的なクエリの例を次に示します。Bigtable Data API を呼び出す同様のクエリの例については、読み取りの例フィルタの使用をご覧ください。

指定された行キーのすべての列の最新バージョンを取得します。

  SELECT * FROM myTable WHERE _key = 'r1'

特定の行キーのすべての列のすべてのバージョンを取得します。

  SELECT * FROM myTable(with_history => TRUE) WHERE _key = 'r1'

特定の行キーの特定の列ファミリーから特定の列の最新バージョンを取得します。

  SELECT stats_summary['os_build'] AS os
  FROM analytics
  WHERE _key = 'phone#4c410523#20190501'

特定の行キー範囲の行キーと、複数の列の最新バージョンを取得します。

  SELECT
    _key,
    stats_summary['os_build'] AS os,
    stats_summary['user_agent'] AS agent
  FROM analytics
  WHERE _key >= 'phone#4c410523#20190501' AND _key < 'phone#4c410523#201906201'

複数の行キー範囲(最大 10 行)のすべての列のすべてのバージョンを取得します。

  SELECT *
  FROM analytics(with_history => TRUE)
  WHERE
    (_key >= 'phone#4c410523#20190501' AND _key < 'phone#4c410523#201906201')
    OR (_key >= 'phone#5c10102#20190501' AND _key < 'phone#5c10102#20190601')
  LIMIT 10

複数の行キーのすべての列のすべてのバージョンを取得します。

  SELECT *
  FROM analytics(with_history => TRUE)
  WHERE _key = 'phone#4c410523#20190501' OR _key = 'phone#4c410523#20190502'

別の方法を使用して、複数の行キーのすべての列のすべてのバージョンを取得します。

  SELECT *
  FROM analytics(with_history => TRUE)
  WHERE _key IS IN ('phone#4c410523#20190501', 'phone#4c410523#20190502')

行キーの接頭辞の列ファミリー内のすべての列の最新バージョンを取得します。

  SELECT stats_summary
  FROM analytics
  WHERE _key LIKE 'phone#%'

テーブル内のすべての行について、列ファミリー内のすべての列の行キーと 3 つの最新バージョンを取得します。このクエリではテーブル全体のスキャンが必要になるため、低レイテンシで高スループットのアクセス パターンにはおすすめしません。

  SELECT _key, cell_plan FROM analytics(with_history => TRUE, latest_n => 3)

指定した正規表現に一致する行キーを持つすべての列の最新バージョンを取得します。このクエリではテーブル全体のスキャンが必要になるため、WHERE 句で行キー接頭辞または行キー範囲の述語も指定しない限り、低レイテンシで高スループットのアクセス パターンにはおすすめしません。

  SELECT *
  FROM myTable(with_history => TRUE)
  WHERE REGEXP_CONTAINS(_key, '.*#20190501$')

一致する行キー接頭辞とカウンタ値が 123 より大きいすべての列の最新バージョンを取得します。Bigtable の集計は数値であるため、この比較でキャストする必要はありません。

  SELECT *
  FROM myTable
  WHERE _key LIKE 'user12%' AND counterFamily['counter'] > 123

リファラーが特定の値と一致した場合に、行キー接頭辞のすべての列の最新バージョンを取得します。

  SELECT *
  FROM analytics
  WHERE _key LIKE 'com.mysite%' AND session['referrer'] = './home'

特定の列の値に基づいて特定の行を分類します。このクエリは、Bigtable Data API で条件付き合成フィルタを使用する場合と似ています。

  SELECT
    *,
    CASE cell_plan['data_plan']
      WHEN '10gb' THEN 'passed-filter'
      ELSE 'filtered-out'
      END
      AS label
  FROM analytics

指定された行キー範囲の特定の列ファミリーの行キーと列修飾子を取得します。SQL では、列ファミリーはマップデータ型で表され、各列修飾子と値は Key-Value ペアとしてマッピングされます。この SQL クエリは、Bigtable Data API で値削除フィルタを使用する場合と似ています。

  SELECT _key, MAP_KEYS(cell_plan) AS keys
  FROM analytics
  WHERE _key >= 'phone#4c410523#20190501' AND _key < 'phone#4c410523#201906201'

高度な Bigtable SQL クエリパターン

次のサンプルは、より高度なパターンを示しています。

次のクエリでは、session 列ファミリーの JSON 属性 abc の行キーと最新の値を取得できます。詳細については、JSON 関数をご覧ください。

  SELECT _key, JSON_VALUE(session['payload'], '$.abc') AS abc FROM analytics

次のクエリでは、行キーを取得し、テーブル内の各行について 2 つの Bigtable 集計セル(数値)の最新の値を使用して平均セッション長を計算できます。

  SELECT
    _key AS userid,
    session['total_minutes'] / session['count'] AS avg_session_length
  FROM analytics

次のクエリでは、session 列ファミリーに列修飾子として referrerorigin、または server が含まれている場合、特定の行キー接頭辞のすべての列の最新バージョンを取得できます。また、このクエリは、session['referrer'] IS NOT NULL OR session['origin'] IS NOT NULL などの一連の個別の比較として記述することもできます。ただし、比較の数が多いクエリの場合は、次の方法をおすすめします。

  SELECT *
  FROM analytics
  WHERE
    _key LIKE 'com.abc%'
    AND ARRAY_INCLUDES_ANY(MAP_KEYS(session), ['referrer', 'origin', 'server'])

次のクエリでは、session 列ファミリーに列修飾子として referreroriginserver が含まれている場合に、特定の行キー接頭辞のすべての列の最新バージョンを取得できます。また、このクエリは、session['referrer'] IS NOT NULL AND session ['origin'] IS NOT NULL のような一連の個別の比較として記述することもできます。

  SELECT *
  FROM analytics
  WHERE
    _key LIKE 'com.abc%'
    AND ARRAY_INCLUDES_ALL(MAP_KEYS(session), ['referrer', 'origin', 'server'])

次のクエリでは、session 列ファミリーに値として com.google.searchcom.google.maps、または com.google.shopping が含まれている場合、特定の行キー接頭辞のすべての列の最新バージョンを取得できます。

  SELECT *
  FROM analytics
  WHERE
    _key LIKE 'com.abc%'
    AND ARRAY_INCLUDES_ANY(
      MAP_VALUES(session),
      ['com.google.search', 'com.google.maps', 'com.google.shopping'])

次のクエリでは、cell_plan 列ファミリーの Key-Value ペアに data_plan:unlimitedroaming:North America の両方が含まれている場合に、すべての列の最新バージョンを取得できます。

  SELECT *
  FROM analytics
  WHERE
    ARRAY_INCLUDES_ALL(
      CAST(
        MAP_ENTRIES(cell_plan)
        AS ARRAY<STRUCT<key STRING, value STRING>>),
      [('data_plan', 'unlimited'), ('roaming', 'North America')])

次のクエリでは、過去 7 回の測定で温度が 70 度を超えたケースの、気象センサーの row keytemperature の測定値を取得できます。

  SELECT
    _key AS sensorid,
    ARRAY_FILTER(
      CAST(
        sensor['temperature']
        AS ARRAY<STRUCT<timestamp TIMESTAMP, value STRING>>),
      e -> CAST(e.value AS FLOAT32) > 70) AS high_temperature
  FROM weather(with_history => TRUE, latest_n => 7)

時間のフィルタリング順序では latest_n が最後に来るため、after => X, before => y, latest_n => 3 のようなクエリは、後と前の条件を満たす最新の 3 つの値を返します。ユースケースで latest_n を優先する必要がある場合は、例で示すように、latest_n を唯一の時間フィルタとして指定してから、SELECT ステートメントでクエリ演算子を使用して残りの時間フィルタを適用します。詳細については、時間フィルタをご覧ください。

  SELECT
    ARRAY_FILTER(
      CAST(
        address['street']
        AS ARRAY<STRUCT<timestamp TIMESTAMP, value STRING>>),
      e -> e.timestamp > TIMESTAMP('2021-01-04 23:51:00+00'))
      AS street_address
  FROM locations(with_history => TRUE, latest_n => 3)

前の例と同様に、クエリの各列ファミリーに異なる時間フィルタを適用できます。たとえば、次のクエリは、street 列の最新の 3 つのバージョンと、state 列の最新の 2 つのバージョンを返します。

  SELECT
    ARRAY_FILTER(
      CAST(
        address['street']
        AS ARRAY<STRUCT<timestamp TIMESTAMP, value STRING>>),
      (e, i) -> i <= 2)
      AS street_address,
    ARRAY_FILTER(
      ARRAY_REVERSE(
        CAST(
          address['state']
          AS ARRAY<STRUCT<timestamp TIMESTAMP, value STRING>>)),
      (e, i) -> i <= 1)
      AS state
  FROM locations(with_history => TRUE)

次のクエリを使用すると、アドレス列ファミリーの Key-Value ペアに city:Savannah または city:Nashville が含まれている場合、すべての列のすべてのバージョンを取得できます。

  SELECT *
  FROM locations(with_history => TRUE)
  WHERE
    ARRAY_LENGTH(
      ARRAY_FILTER(
        CAST(
          MAP_ENTRIES(address)
          AS ARRAY<
            STRUCT<
              key STRING,
              value ARRAY<STRUCT<timestamp TIMESTAMP, value STRING>>>>),
        e ->
          e.key = 'city'
          AND ARRAY_INCLUDES_ANY(
            ARRAY_TRANSFORM(e.value, k -> k.value), ['Savannah', 'Nashville'])))
    > 0

この例ではキャスティングが不要なため、次の短い形式で記述することもできます。

  SELECT *
  FROM locations(with_history => TRUE)
  WHERE
    ARRAY_LENGTH(
      ARRAY_FILTER(
        MAP_ENTRIES(address),
        e ->
          e.key = 'city'
          AND ARRAY_INCLUDES_ANY(
            ARRAY_TRANSFORM(e.value, k -> k.value), ['Savannah', 'Nashville'])))
    > 0

次のステップ