Consultar dados do Bigtable

Neste documento, descrevemos como consultar dados armazenados em uma tabela externa do Cloud Bigtable.

O Bigtable é o banco de dados NoSQL do Google, preenchido de maneira esparsa, que é capaz de se expandir a bilhões de linhas, milhares de colunas e petabytes de dados. Para informações sobre o modelo de dados do Bigtable, consulte Modelo de armazenamento.

Consultar tabelas externas permanentes

Antes de começar, você ou alguém da sua organização precisa criar uma tabela externa para usar. Para mais detalhes e permissões necessárias, consulte Criar uma tabela externa do BigQuery.

Papéis obrigatórios

Para consultar tabelas externas permanentes do Bigtable, verifique se você tem os seguintes papéis:

  • Leitor de dados do BigQuery (roles/bigquery.dataViewer)
  • Usuário do BigQuery (roles/bigquery.user)
  • Leitor do BigQuery (roles/bigtable.reader)

Dependendo das suas permissões, é possível conceder esses papéis a você mesmo ou pedir ao administrador para concedê-los. Para mais informações sobre como conceder papéis, consulte Como visualizar os papéis atribuíveis em recursos.

Para ver as permissões exatas do BigQuery necessárias para consultar tabelas externas, expanda a seção Permissões necessárias:

Permissões necessárias

Essas permissões também podem ser concedidas com papéis personalizados ou outros papéis predefinidos.

consulte a tabela

É possível executar uma consulta em uma tabela externa permanente do Bigtable exatamente como se fosse uma tabela padrão do BigQuery, sujeito a limitações em fontes de dados externas. Para mais informações, consulte Executar consultas interativas e em lote.

Consultar tabelas externas temporárias

A consulta a uma fonte de dados externa usando uma tabela temporária é útil quando você quer consultar dados externos apenas uma vez, com um propósito específico, ou executar processos de Extração, transformação e carregamento (ETL).

Para consultar uma fonte de dados externa sem criar uma tabela permanente, forneça uma definição de tabela para a tabela temporária e use-a em um comando ou uma chamada para consultar a tabela temporária. É possível fornecer a definição da tabela de uma destas maneiras:

O arquivo de definição de tabela ou esquema fornecido é usado para criar a tabela externa temporária, e a consulta será executada nela.

A tabela externa temporária não é criada em um dos conjuntos de dados do BigQuery. Como ela não fica armazenada permanentemente em um conjunto de dados, não é possível compartilhá-la com outros.

O uso de uma tabela externa temporária em vez de uma tabela externa permanente tem algumas limitações, incluindo o seguinte:

  • Você precisa ter o papel de Administrador do Bigtable (roles/bigtable.admin).
  • Com essa abordagem, não é possível usar o console do Google Cloud para inferir o esquema da tabela do Bigtable e criar automaticamente a definição da tabela. Crie a definição da tabela por conta própria.

Papéis obrigatórios

Para consultar tabelas externas temporárias do Bigtable, verifique se você tem os seguintes papéis:

  • Leitor de dados do BigQuery (roles/bigquery.dataViewer)
  • Usuário do BigQuery (roles/bigquery.user)
  • Administrador do BigQuery (roles/bigtable.admin)

Dependendo das suas permissões, é possível conceder esses papéis a você mesmo ou pedir ao administrador para concedê-los. Para mais informações sobre como conceder papéis, consulte Como visualizar os papéis atribuíveis em recursos.

Para ver as permissões exatas do BigQuery necessárias para consultar tabelas externas, expanda a seção Permissões necessárias:

Permissões necessárias

Essas permissões também podem ser concedidas com papéis personalizados ou outros papéis predefinidos.

Criar e consultar a tabela

Para consultar dados do Bigtable usando uma tabela externa temporária, você:

No momento, a criação e a consulta de uma tabela externa temporária é possível usando a ferramenta de linha de comando bq e a API.

bq

Para consultar uma tabela temporária usando um arquivo de definição de tabela, insira o comando bq query com a sinalização --external_table_definition.

Opcional: forneça a sinalização --location e defina o valor do local.

bq --location=LOCATION query \
--use_legacy_sql=false \
--external_table_definition=TABLE::DEFINITION_FILE \
'QUERY'

Substitua:

  • LOCATION: o nome do seu local. A sinalização --location é opcional.
  • TABLE: o nome da tabela temporária que você está criando
  • DEFINITION_FILE: o caminho para o arquivo de definição de tabelas na máquina local.
  • QUERY: a consulta que você está enviando para a tabela temporária.

Por exemplo, o comando a seguir cria e consulta uma tabela temporária chamada follows usando um arquivo de definição de tabela chamado follows_def.

bq query \
--use_legacy_sql=false \
--external_table_definition=follows::/tmp/follows_def \
'SELECT
  COUNT(rowkey)
 FROM
   follows'

API

  • Crie uma consulta. Consulte Como consultar dados para informações sobre como criar um job de consulta.

  • (Opcional) Especifique seu local na propriedade location, na seção jobReference do recurso do job.

  • Especifique as propriedades da fonte de dados externa definindo a ExternalDataConfiguration para o recurso de tabela.

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, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

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.TableResult;
import com.google.common.collect.ImmutableList;
import org.apache.commons.codec.binary.Base64;

// Sample to queries an external bigtable data source using a temporary table
public class QueryExternalBigtableTemp {

  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 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);
    queryExternalBigtableTemp(bigqueryTableName, sourceUri, query);
  }

  public static void queryExternalBigtableTemp(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();

      // Configure the external data source and query job.
      ExternalTableDefinition externalTable =
          ExternalTableDefinition.newBuilder(sourceUri, options).build();
      QueryJobConfiguration queryConfig =
          QueryJobConfiguration.newBuilder(query)
              .addTableDefinition(tableName, externalTable)
              .build();

      // Example query
      TableResult results = bigquery.query(queryConfig);

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

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

Considerações sobre desempenho

O desempenho das consultas em fontes de dados externas do Bigtable depende de três fatores:

  • número de linhas
  • volume de dados lidos
  • extensão do carregamento em paralelo

O BigQuery tenta ler o mínimo de dados possível ao ler somente os grupos de colunas referenciados na consulta. A extensão do carregamento em paralelo depende de quantos nós você tem no cluster do Bigtable e de quantas divisões há na tabela.

O Bigtable mescla automaticamente as divisões com base no carregamento. Se a tabela não for lida com frequência, haverá menos divisões ao longo do tempo e uma degradação gradual no desempenho da consulta. Para mais informações sobre como dividir uma tabela por chave de linha, consulte Como gerenciar tabelas.

A consulta ao Bigtable no BigQuery consome ciclos de CPU do Bigtable. O consumo de CPU pelo BigQuery pode afetar a latência e a capacidade de outras solicitações simultâneas, como exibir tráfego do usuário ativo. Por exemplo, o alto uso da CPU no Bigtable afeta consultas extensas e aumenta a latência no 99º percentil.

É preciso monitorar o uso da CPU do Bigtable para verificar se está dentro dos limites recomendados, conforme observado no painel de monitoramento do Bigtable no console do Google Cloud. Aumentar o número de nós para a instância permite processar melhor o tráfego do BigQuery e o tráfego de outras solicitações simultâneas.

Filtros da consulta

As consultas com filtro de igualdade de linha leem somente a linha específica. Por exemplo, na sintaxe do GoogleSQL:

SELECT
  COUNT(follows.column.name)
FROM
  `dataset.table`
WHERE
  rowkey = "alice";

Os filtros de intervalo, como rowkey > '1' e rowkey < '8', também são compatíveis, mas somente quando rowkey é lido como uma string com a opção readRowkeyAsString.