Criar uma tabela externa do Bigtable

Nesta página, descrevemos como criar uma tabela externa permanente do BigQuery que pode ser usada para consultar dados armazenados no Bigtable. A consulta de dados no Bigtable está disponível em todos os locais do Bigtable.

Antes de começar

Antes de criar uma tabela externa, colete algumas informações e verifique se você tem permissão para criar a tabela.

Funções exigidas

Para criar uma tabela externa para consultar seus dados do Bigtable, é necessário ser um principal no papel de Administrador do Bigtable (roles/bigtable.admin) para a instância que contém a tabela de origem.

Você também precisa da permissão bigquery.tables.create do Identity and Access Management (IAM).

Cada um dos seguintes papéis predefinidos do Identity and Access Management inclui esta permissão:

  • Editor de dados do BigQuery (roles/bigquery.dataEditor)
  • Proprietário de dados do BigQuery (roles/bigquery.dataOwner)
  • Administrador do BigQuery (roles/bigquery.admin)

Se você não for um principal em qualquer um desses papéis, peça ao administrador para conceder acesso a você ou criar a tabela externa para você.

Para mais informações sobre os papéis e as permissões do Identity and Access Management no BigQuery, consulte Papéis e permissões predefinidos. Para ver informações sobre as permissões do Bigtable, consulte Controle de acesso com o Identity and Access Management.

Criar ou identificar um conjunto de dados

Antes de criar uma tabela externa, você precisa criar um conjunto de dados para contê-la. Também é possível usar um projeto atual.

Opcional: designar ou criar um cluster

Se você pretende consultar com frequência os mesmos dados que veiculam o aplicativo de produção, recomendamos designar um cluster na instância do Bigtable para ser usado apenas para análise do BigQuery. Isso isola o tráfego dos clusters que você usa para as leituras e gravações do aplicativo. Para saber mais sobre replicação e criação de instâncias com mais de um cluster, consulte Sobre replicação.

Identificar ou criar um perfil de app

Antes de criar uma tabela externa, decida qual perfil de aplicativo do Bigtable o BigQuery deve usar para ler os dados. Recomendamos que você use um perfil de app designado para ser usado somente com o BigQuery.

Se você tiver um cluster na instância do Bigtable dedicado ao acesso ao BigQuery, configure o perfil de aplicativo para usar o roteamento de cluster único para esse cluster.

Para saber como os perfis do aplicativo Bigtable funcionam, consulte Sobre perfis de apps. Para ver como criar um novo perfil de app, consulte Criar e configurar perfis de app.

Recuperar o URI do Bigtable

Para criar uma tabela externa para uma fonte de dados do Bigtable, você precisa fornecer o URI do Bigtable. Para recuperar o URI do Bigtable, faça o seguinte:

  1. Abra a página do Bigtable no console.

    Acessar o Bigtable

  2. Recupere os seguintes detalhes sobre a fonte de dados do Bigtable:

    • o código do projeto
    • Seu ID da instância do Bigtable
    • O ID do perfil do app Bigtable que você planeja usar
    • O nome da tabela do Bigtable
  3. Escreva o URI do Bigtable usando o seguinte formato, em que:

    • project_id é o projeto que contém a instância do Bigtable.
    • instance_id é o ID da instância do Bigtable
    • (Opcional) app_profile é o ID do perfil do aplicativo que você quer usar.
    • table_name é o nome da tabela que você está consultando.

    https://googleapis.com/bigtable/projects/project_id/instances/instance_id[/appProfiles/app_profile]/tables/table_name

Criar tabelas externas permanentes

Quando você cria uma tabela externa permanente no BigQuery vinculada a uma fonte de dados do Bigtable, há duas opções para especificar o formato dela:

  • Se estiver usando a API ou a ferramenta de linha de comando bq, crie um arquivo de definição de tabela que define o esquema e os metadados da tabela externa.
  • Caso esteja usando SQL, use a opção uri da instrução CREATE EXTERNAL TABLE para especificar a tabela do Bigtable de que os dados serão extraídos e a opção bigtable_options para especificar o esquema da tabela.

Os dados da tabela externa não são armazenados na tabela do BigQuery. Como a tabela é permanente, é possível usar controles de acesso no nível do conjunto de dados para compartilhar a tabela com outras pessoas que também tenham acesso à fonte de dados subjacente do Bigtable.

Para criar uma tabela permanente, escolha um dos métodos a seguir.

SQL

É possível criar uma tabela externa permanente executando a instrução DDL CREATE EXTERNAL TABLE. Especifique o esquema da tabela explicitamente como parte das opções de instrução.

  1. No Console do Google Cloud, acesse a página BigQuery.

    Ir para o BigQuery

  2. No editor de consultas, digite a seguinte instrução:

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

    Substitua:

    • DATASET: o conjunto de dados em que a tabela externa do Bigtable será criada.
    • NEW_TABLE: o nome da tabela externa do Bigtable.
    • URI: o URI da tabela do Bigtable que você quer usar como fonte de dados. Esse URI precisa seguir o formato descrito em Como recuperar o URI do Bigtable.
    • BIGTABLE_OPTIONS: o esquema da tabela do Bigtable no formato JSON. Para conferir uma lista de opções de definição de tabela do Bigtable, consulte BigtableOptions na Referência da API REST.

  3. Clique em Executar.

Para mais informações sobre como executar consultas, acesse Executar uma consulta interativa.

Uma instrução para criar uma tabela externa do Bigtable pode ser semelhante a esta:

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

bq

Crie uma tabela na ferramenta de linha de comando bq usando o comando bq mk. Ao usar a ferramenta de linha de comando bq para criar uma tabela vinculada a uma fonte de dados externa, você identifica o esquema da tabela usando um arquivo de definição de tabela.

  1. Use o comando bq mk para criar uma tabela permanente.

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

    Substitua:

    • DEFINITION_FILE: o caminho para o arquivo de definição de tabelas na máquina local.
    • DATASET: o nome do conjunto de dados onde está a tabela.
    • TABLE: o nome da tabela que você está criando;

API

Use os métodos de API tables.insert e crie um ExternalDataConfiguration no recurso Table que você transmite.

Para a propriedade sourceUris no recurso Table, especifique apenas um URI do Bigtable. Ele precisa ser um URL HTTPS válido.

Para a propriedade sourceFormat, especifique "BIGTABLE".

Java

Antes de testar esta amostra, siga as instruções de configuração do Java no Guia de início rápido do BigQuery: como usar bibliotecas de cliente. Para mais informações, consulte a documentação de referência da API BigQuery em Java.

Para autenticar no BigQuery, configure o Application Default Credentials. Para mais informações, acesse Configurar a autenticação para bibliotecas de cliente.

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());
    }
  }
}

Consultar tabelas externas

Para mais informações, consulte Consultar dados do Bigtable.

Esquema gerado

Por padrão, o BigQuery expõe os valores em um grupo de colunas como uma matriz de colunas e, nela, uma matriz de valores gravados em carimbos de data/hora diferentes. Esse esquema preserva o layout natural dos dados no Cloud Bigtable, mas as consultas SQL podem ser complexas. É possível promover colunas a subcampos no grupo de colunas pai e ler somente o último valor de cada célula. Isso representa as duas matrizes no esquema padrão como valores escalares.

Exemplo

Você armazena perfis de usuários em uma rede social fictícia. Um modelo de dados para esse caso pode ser um grupo de colunas profile com colunas individuais para gender, age e email:

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

Usando o esquema padrão, a consulta do GoogleSQL para contar o número de usuários do sexo masculino acima de 30 anos é:

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)

A consulta de dados será menos desafiadora se gender e age forem expostos como subcampos. Para isso, marque gender e age como colunas nomeadas no grupo de colunas profile ao definir a tabela. Também é possível instruir o BigQuery a expor os valores mais recentes desse grupo de colunas porque normalmente apenas o valor mais recente e, possivelmente, o único valor é de interesse.

Depois de expor as colunas como subcampos, a consulta do GoogleSQL para contar o número de usuários do sexo masculino com mais de 30 anos será:

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

Observe como gender e age são referenciados diretamente como campos. A configuração JSON para essa definição é:

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

Codificação de valor

O Bigtable armazena os dados como bytes brutos, independentes da codificação de dados. No entanto, os valores de bytes têm uso limitado nas análises de consultas SQL. O Bigtable oferece dois tipos básicos de decodificação escalar: texto e binária do HBase.

O formato de texto considera que todos os valores são armazenados como strings de texto alfanuméricas. Por exemplo, o número inteiro 768 será armazenado como a string "768". A codificação binária considera que a classe de métodos Bytes.toBytes do HBase foi usada para codificar os dados e aplica um método de decodificação apropriado.

Zonas e regiões com suporte

A consulta de dados no Bigtable está disponível em todas as zonas do Bigtable compatíveis. Veja a lista de zonas aqui. Para instâncias de vários clusters, o BigQuery roteia o tráfego com base nas configurações de perfil de app do Bigtable.

Limitações

Para informações sobre limitações aplicáveis a tabelas externas, consulte Limitações de tabelas externas.

Escopos de instâncias do Compute Engine

Ao criar uma instância do Compute Engine, especifique uma lista de escopos para ela. Os escopos controlam o acesso da instância aos produtos do Google Cloud, entre eles, o Bigtable. Os aplicativos em execução na VM usam a conta de serviço para chamar as APIs do Google Cloud.

Se você configurar uma instância do Compute Engine para ser executada como uma conta de serviço e essa conta acessar uma tabela externa vinculada a uma fonte de dados do Bigtable, será necessário adicionar o escopo de acesso de dados somente leitura do Bigtable (https://www.googleapis.com/auth/bigtable.data.readonly) para a instância. Para mais informações, consulte Como criar uma instância do Compute Engine para o Bigtable.

Para mais informações sobre como aplicar escopos a uma instância do Compute Engine, consulte Como alterar a conta de serviço e os escopos de acesso de uma instância. Acesse Contas de serviço para saber mais sobre esse tipo de conta do Compute Engine.

A seguir