建立 Bigtable 外部資料表

本頁面說明如何建立 BigQuery 永久外部資料表,用於查詢儲存在 Bigtable 中的資料。您可以在所有 Bigtable 地點中查詢 Bigtable 中的資料。

事前準備

建立外部資料表前,請先收集一些資訊,並確認您有權建立資料表。

必要的角色

如要建立外部資料表,以便用於查詢 Bigtable 資料,您必須是包含來源資料表的執行個體中 Bigtable 管理員 (roles/bigtable.admin) 角色中的實體。

您也需要 bigquery.tables.create BigQuery Identity and Access Management (IAM) 權限。

以下每個預先定義的 Identity and Access Management 角色都包含這項權限:

  • BigQuery 資料編輯器 (roles/bigquery.dataEditor)
  • BigQuery 資料擁有者 (roles/bigquery.dataOwner)
  • BigQuery 管理員 (roles/bigquery.admin)

如果您不是上述任一角色的實體,請要求管理員授予存取權,或為您建立外部資料表。

如要進一步瞭解 BigQuery 中的 Identity and Access Management 角色和權限,請參閱「預先定義的角色和權限」一文。如要查看 Bigtable 權限相關資訊,請參閱「使用身分與存取權管理功能控管存取權」。如要查看查詢外部資料表所需的角色,請參閱「查詢 Bigtable 資料」。

建立或識別資料集

建立外部資料表前,您必須建立資料集來容納外部資料表。您也可以使用現有資料集。

規劃運算用量

決定要用於查詢資料的運算類型。您可以在應用程式設定檔設定中指定要使用 Data Boost,或要將資料傳送至專屬叢集。

Data Boost

為避免影響應用程式服務流量,您可以使用 BigQuery 外部資料表讀取 Bigtable 資料時,使用 Data Boost 無伺服器運算功能。如要使用 Data Boost,您必須使用 Data Boost 應用程式設定檔,並在組合 Bigtable URI 時加入應用程式設定檔 ID。如要進一步瞭解 Data Boost,請參閱 Bigtable Data Boost 總覽

已佈建的節點

如果您未使用 Data Boost,系統會使用叢集節點進行運算。

如果您不使用 Data Boost,且打算經常查詢用於服務實際應用程式的相同資料,建議您在 Bigtable 執行個體中指定一個叢集,專門用於 BigQuery 分析。這會將流量與您用於應用程式讀取和寫入作業的叢集區隔開來。如要進一步瞭解複製功能和建立含有多個叢集的執行個體,請參閱「關於複製功能」。

識別或建立應用程式設定檔

建立外部資料表前,請決定 BigQuery 應使用哪個 Bigtable 應用程式設定檔來讀取資料。建議您使用專門用於 BigQuery 的應用程式設定檔。應用程式設定檔可以是標準應用程式設定檔或 Data Boost 應用程式設定檔,取決於您要用來查詢資料的運算類型。

如果 Bigtable 執行個體中有專門用於 BigQuery 存取權的叢集,請將應用程式設定檔設為使用單一叢集路由至該叢集。

如要使用 Data Boost 無伺服器運算,請建立 Data Boost 應用程式設定檔。如要使用叢集節點進行運算,請建立標準應用程式設定檔。如要瞭解 Bigtable 應用程式設定檔的運作方式,請參閱「關於應用程式設定檔」。如要瞭解如何建立新的應用程式設定檔,請參閱「建立及設定應用程式設定檔」。

擷取 Bigtable URI

如要為 Bigtable 資料來源建立外部資料表,則必須提供 Bigtable URI。如要擷取 Bigtable URI,請按照下列步驟操作:

  1. 在主控台中開啟 Bigtable 頁面。

    前往 Bigtable

  2. 擷取 Bigtable 資料來源的以下詳細資料:

    • 您的專案 ID。
    • 您的 Bigtable 執行個體 ID。
    • 您要使用的 Bigtable 應用程式設定檔 ID。這可以是標準應用程式設定檔或 Data Boost 應用程式設定檔,取決於您要使用的運算類型。如果您未指定應用程式設定檔 ID,系統會使用預設應用程式設定檔。
    • Bigtable 資料表的名稱。
  3. 以下列格式撰寫 Bigtable URI,其中:

    • PROJECT_ID 是包含 Bigtable 執行個體的專案
    • INSTANCE_ID 是 Bigtable 執行個體 ID
    • APP_PROFILE (選用) 是您要使用的應用程式設定檔 ID
    • TABLE_NAME 是您要查詢的資料表名稱

    https://googleapis.com/bigtable/projects/PROJECT_ID/instances/INSTANCE_ID[/appProfiles/APP_PROFILE]/tables/TABLE_NAME

建立永久外部資料表

在 BigQuery 中建立連結至 Bigtable 資料來源的永久外部資料表時,有兩種方法可指定外部資料表的格式:

  • 如果您使用 API 或 bq 指令列工具,請建立資料表定義檔,以定義外部資料表的結構定義與中繼資料。
  • 如果您使用 SQL,請使用 CREATE EXTERNAL TABLE 陳述式的 uri 選項,指定要從中擷取資料的 Bigtable 資料表,並使用 bigtable_options 選項指定資料表結構定義。

外部資料表資料不會儲存在 BigQuery 資料表中。因為資料表為永久性,因此您可以使用資料集層級存取權控管機制,將資料表分享給也能存取基礎 Bigtable 資料來源的其他使用者。

如要建立永久資料表,請選擇下列任一方法。

SQL

您可以執行 CREATE EXTERNAL TABLE DDL 陳述式,建立永久外部資料表。您必須在陳述式選項中明確指定資料表結構定義。

  1. 前往 Google Cloud 控制台的「BigQuery」頁面。

    前往 BigQuery

  2. 在查詢編輯器中輸入以下陳述式:

    CREATE EXTERNAL TABLE DATASET.NEW_TABLE
    OPTIONS (
      format = 'CLOUD_BIGTABLE',
      uris = ['URI'],
      bigtable_options = BIGTABLE_OPTIONS );

    請依指示取代下列項目:

    • DATASET:用於建立 Bigtable 外部資料表的資料集。
    • NEW_TABLE:Bigtable 外部資料表的名稱。
    • URI:您要用來做為資料來源的 Bigtable 資料表 URI。這個 URI 必須符合「擷取 Bigtable URI」一節所述的格式。
    • BIGTABLE_OPTIONS:Bigtable 資料表的結構定義,以 JSON 格式表示。如需 Bigtable 資料表定義選項清單,請參閱 REST API 參考資料中的 BigtableOptions

  3. 按一下 「Run」

如要進一步瞭解如何執行查詢,請參閱「執行互動式查詢」一文。

建立外部 Bigtable 資料表的陳述式可能類似以下內容:

CREATE EXTERNAL TABLE mydataset.BigtableTable
OPTIONS (
  format = 'CLOUD_BIGTABLE',
  uris = ['https://googleapis.com/bigtable/projects/myproject/instances/myBigtableInstance/appProfiles/myAppProfile/tables/table1'],
  bigtable_options =
    """
    {
      columnFamilies: [
        {
          "familyId": "familyId1",
          "type": "INTEGER",
          "encoding": "BINARY"
        }
      ],
      readRowkeyAsString: true
    }
    """
);

bq

您可以在 bq 指令列工具中使用 bq mk 指令建立資料表。使用 bq 指令列工具建立連結至外部資料來源的資料表時,您可以使用資料表定義檔識別資料表的結構定義。

  1. 使用 bq mk 指令建立永久資料表。

    bq mk \
    --external_table_definition=DEFINITION_FILE \
    DATASET.TABLE

    更改下列內容:

    • DEFINITION_FILE:本機電腦上資料表定義檔的路徑。
    • DATASET:含有資料表的資料集名稱。
    • TABLE:您要建立的資料表名稱。

API

使用 tables.insert API 方法,並在您傳入的 Table 資源中建立 ExternalDataConfiguration

針對 Table 資源中的 sourceUris 屬性,只指定一個 Bigtable URI。必須是有效的 HTTPS 網址。

針對 sourceFormat 屬性,請指定 "BIGTABLE"

Java

在嘗試這個範例之前,請先按照 BigQuery 快速入門:使用用戶端程式庫中的 Java 設定說明進行操作。詳情請參閱 BigQuery Java API 參考說明文件

如要向 BigQuery 進行驗證,請設定應用程式預設憑證。詳情請參閱「設定用戶端程式庫的驗證機制」。

import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.BigtableColumn;
import com.google.cloud.bigquery.BigtableColumnFamily;
import com.google.cloud.bigquery.BigtableOptions;
import com.google.cloud.bigquery.ExternalTableDefinition;
import com.google.cloud.bigquery.QueryJobConfiguration;
import com.google.cloud.bigquery.TableId;
import com.google.cloud.bigquery.TableInfo;
import com.google.cloud.bigquery.TableResult;
import com.google.common.collect.ImmutableList;
import org.apache.commons.codec.binary.Base64;

// Sample to queries an external bigtable data source using a permanent table
public class QueryExternalBigtablePerm {

  public static void main(String[] args) {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "MY_PROJECT_ID";
    String bigtableInstanceId = "MY_INSTANCE_ID";
    String bigtableTableName = "MY_BIGTABLE_NAME";
    String bigqueryDatasetName = "MY_DATASET_NAME";
    String bigqueryTableName = "MY_TABLE_NAME";
    String sourceUri =
        String.format(
            "https://googleapis.com/bigtable/projects/%s/instances/%s/tables/%s",
            projectId, bigtableInstanceId, bigtableTableName);
    String query = String.format("SELECT * FROM %s ", bigqueryTableName);
    queryExternalBigtablePerm(bigqueryDatasetName, bigqueryTableName, sourceUri, query);
  }

  public static void queryExternalBigtablePerm(
      String datasetName, String tableName, String sourceUri, String query) {
    try {
      // Initialize client that will be used to send requests. This client only needs to be created
      // once, and can be reused for multiple requests.
      BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();

      BigtableColumnFamily.Builder statsSummary = BigtableColumnFamily.newBuilder();

      // Configuring Columns
      BigtableColumn connectedCell =
          BigtableColumn.newBuilder()
              .setQualifierEncoded(Base64.encodeBase64String("connected_cell".getBytes()))
              .setFieldName("connected_cell")
              .setType("STRING")
              .setEncoding("TEXT")
              .build();
      BigtableColumn connectedWifi =
          BigtableColumn.newBuilder()
              .setQualifierEncoded(Base64.encodeBase64String("connected_wifi".getBytes()))
              .setFieldName("connected_wifi")
              .setType("STRING")
              .setEncoding("TEXT")
              .build();
      BigtableColumn osBuild =
          BigtableColumn.newBuilder()
              .setQualifierEncoded(Base64.encodeBase64String("os_build".getBytes()))
              .setFieldName("os_build")
              .setType("STRING")
              .setEncoding("TEXT")
              .build();

      // Configuring column family and columns
      statsSummary
          .setColumns(ImmutableList.of(connectedCell, connectedWifi, osBuild))
          .setFamilyID("stats_summary")
          .setOnlyReadLatest(true)
          .setEncoding("TEXT")
          .setType("STRING")
          .build();

      // Configuring BigtableOptions is optional.
      BigtableOptions options =
          BigtableOptions.newBuilder()
              .setIgnoreUnspecifiedColumnFamilies(true)
              .setReadRowkeyAsString(true)
              .setColumnFamilies(ImmutableList.of(statsSummary.build()))
              .build();

      TableId tableId = TableId.of(datasetName, tableName);
      // Create a permanent table linked to the Bigtable table
      ExternalTableDefinition externalTable =
          ExternalTableDefinition.newBuilder(sourceUri, options).build();
      bigquery.create(TableInfo.of(tableId, externalTable));

      // Example query
      TableResult results = bigquery.query(QueryJobConfiguration.of(query));

      results
          .iterateAll()
          .forEach(row -> row.forEach(val -> System.out.printf("%s,", val.toString())));

      System.out.println("Query on external permanent table performed successfully.");
    } catch (BigQueryException | InterruptedException e) {
      System.out.println("Query not performed \n" + e.toString());
    }
  }
}

查詢外部資料表

詳情請參閱「查詢 Bigtable 資料」。

產生的結構定義

根據預設,BigQuery 會將資料欄系列中的值以資料欄陣列的形式呈現,並在其中提供在不同時間戳記寫入的值陣列。這個結構定義會保留 Bigtable 中資料的自然配置,但執行 SQL 查詢可能會有困難。您可以將資料欄升級為父資料欄系列中的子欄位,並僅讀取各儲存格最新的值。這會將預設結構定義中的兩個陣列以純量值的方式呈現。

範例

您要儲存虛擬社交網路的使用者個人資料。其中一個資料模型可能會是 profile 資料欄系列加上 genderageemail 的個別資料欄:

rowkey | profile:gender| profile:age| profile:email
-------| --------------| -----------| -------------
alice  | female        | 30         | alice@gmail.com

使用預設結構定義時,計算超過 30 歲的男性使用者人數的 GoogleSQL 查詢如下:

SELECT
  COUNT(1)
FROM
  `dataset.table`
OMIT
  RECORD IF NOT SOME(profile.column.name = "gender"
    AND profile.column.cell.value = "male")
  OR NOT SOME(profile.column.name = "age"
    AND INTEGER(profile.column.cell.value) > 30)

如果 genderage 以子欄位的形式呈現,要查詢資料就相對簡單許多。如要以子欄位的形式呈現這些項目,請在定義資料表時將 genderage 列為 profile 資料欄系列中的已命名資料欄。您也可以指示 BigQuery 顯示這個資料欄系列的最新值,因為一般來說,只有最新的值 (可能也是唯一值) 才需要注意。

將資料欄以子欄位的形式呈現時,計算超過 30 歲之男性使用者人數的 GoogleSQL 查詢如下:

SELECT
  COUNT(1)
FROM
  `dataset.table`
WHERE
  profile.gender.cell.value="male"
  AND profile.age.cell.value > 30

請注意,查詢是直接以欄位形式參照 genderage。此設定的 JSON 設定如下:

  "bigtableOptions": {
    "readRowkeyAsString": "true",
    "columnFamilies": [
      {
          "familyId": "profile",
          "onlyReadLatest": "true",
          "columns": [
              {
                  "qualifierString": "gender",
                  "type": "STRING"
              },
              {
                  "qualifierString": "age",
                  "type": "INTEGER"
              }
          ]
      }
    ]
  }

值編碼

Bigtable 會將資料儲存為原始位元組,不受資料編碼影響。然而,位元組值在 SQL 查詢分析中的用途有限。Bigtable 提供兩種基本類型的純量解碼:文字和 HBase 二進位解碼。

文字格式假定所有的值都會儲存為英數文字字串。例如,整數 768 會儲存為字串「768」。二進位檔編碼假定之前採用的 HBase Bytes.toBytes 方法類別是用來編碼資料,並套用適當的解碼方法。

支援的地區與區域

您可以在所有支援的 Bigtable 區域中查詢 Bigtable 資料。如需區域清單,請參閱這篇文章。對於多叢集執行個體,BigQuery 會根據 Bigtable 應用程式設定檔設定轉送流量。

限制

  • 您無法在以 Bigtable SQL 為基礎的物件 (例如檢視表和持續性 materialized view) 上建立外部資料表。
  • 如要進一步瞭解適用於外部資料表的限制,請參閱「外部資料表限制」。

Compute Engine 執行個體的範圍

建立 Compute Engine 執行個體時,您可以指定執行個體的範圍清單。這些範圍會控管執行個體對 Google Cloud產品 (包括 Bigtable) 的存取權。在 VM 上執行的應用程式會透過服務帳戶呼叫 Google Cloud API。

如果將 Compute Engine 執行個體設為以服務帳戶的形式執行,且該服務帳戶會存取連結至 Bigtable 資料來源的外部資料表,則您必須為執行個體新增 Bigtable 唯讀資料存取權範圍 (https://www.googleapis.com/auth/bigtable.data.readonly)。如需詳細資訊,請參閱「為 Bigtable 建立 Compute Engine 執行個體」。

如需為 Compute Engine 執行個體套用範圍的相關資訊,請參閱變更執行個體的服務帳戶與存取權範圍一節。如要進一步瞭解 Compute Engine 服務帳戶,請參閱服務帳戶一文。

後續步驟