建立 Bigtable 外部資料表

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

事前準備

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

必要的角色

如要建立外部資料表來查詢 Bigtable 資料,您必須是來源資料表所在執行個體的 Bigtable 管理員 (roles/bigtable.admin) 角色主體。

您也需要 bigquery.tables.create BigQuery 身分與存取權管理 (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:JSON 格式的 Bigtable 資料表結構定義。如需 Bigtable 資料表定義選項清單,請參閱 REST API 參考資料中的 BigtableOptions

  3. 按一下「執行」

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

建立外部 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         | [email protected]

使用預設結構定義時,計算超過 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 服務帳戶,請參閱服務帳戶一文。

後續步驟