Consulte dados do Bigtable

Este documento descreve como usar o BigQuery para consultar dados armazenados numa tabela externa do Bigtable. Para obter informações sobre como consultar dados diretamente do Bigtable, consulte a vista geral do GoogleSQL para Bigtable.

O Bigtable é a base de dados NoSQL com poucos dados da Google que pode ser dimensionada para milhares de milhões de linhas, milhares de colunas e petabytes de dados. Para obter informações sobre o modelo de dados do Bigtable, consulte o artigo Modelo de armazenamento.

Consultar tabelas externas permanentes

Antes de começar, tem de criar uma tabela externa ou um administrador da sua organização tem de o fazer para que a possa usar. Para ver detalhes e autorizações necessárias, consulte o artigo Crie uma tabela externa do BigQuery.

Funções necessárias

Para consultar tabelas externas do Bigtable, certifique-se de que tem as seguintes funções.

  • Visualizador de dados do BigQuery (roles/bigquery.dataViewer)
  • Utilizador do BigQuery (roles/bigquery.user)
  • Leitor do Bigtable (roles/bigtable.reader)

Consoante as suas autorizações, pode atribuir estas funções a si próprio ou pedir ao seu administrador para as atribuir. Para mais informações sobre a concessão de funções, consulte o artigo Ver as funções atribuíveis aos recursos.

Para ver as autorizações exatas do BigQuery necessárias para consultar tabelas externas, expanda a secção Autorizações necessárias:

Autorizações necessárias

Também pode conseguir estas autorizações com funções personalizadas ou outras funções predefinidas.

Consulte a tabela

Pode executar uma consulta numa tabela Bigtable externa permanente exatamente como se fosse uma tabela BigQuery padrão, sujeita às limitações nas origens de dados externas. Para mais informações, consulte o artigo Execute consultas interativas e em lote.

Consultar tabelas externas temporárias

A consulta de uma origem de dados externa através de uma tabela temporária é útil para consultas únicas e ad hoc sobre dados externos ou para processos de extração, transformação e carregamento (ETL).

Para consultar uma origem de dados externa sem criar uma tabela permanente, fornece uma definição de tabela para a tabela temporária e, em seguida, usa essa definição de tabela num comando ou numa chamada para consultar a tabela temporária. Pode fornecer a definição da tabela de qualquer uma das seguintes formas:

O ficheiro de definição da tabela ou o esquema fornecido é usado para criar a tabela externa temporária e a consulta é executada na tabela externa temporária.

Quando usa uma tabela externa temporária, não cria uma tabela num dos seus conjuntos de dados do BigQuery. Uma vez que a tabela não está armazenada permanentemente num conjunto de dados, não pode ser partilhada com outras pessoas.

A utilização de uma tabela externa temporária em vez de uma tabela externa permanente tem algumas limitações, incluindo as seguintes:

  • Tem de ter a função de administrador do Bigtable (roles/bigtable.admin).
  • Esta abordagem não lhe permite usar a Google Cloud consola para inferir o esquema da tabela do Bigtable e criar automaticamente a definição da tabela. Tem de criar a definição da tabela.

Funções necessárias

Para consultar tabelas externas temporárias do Bigtable, certifique-se de que tem as seguintes funções:

  • Visualizador de dados do BigQuery (roles/bigquery.dataViewer)
  • Utilizador do BigQuery (roles/bigquery.user)
  • Administrador do Bigtable (roles/bigtable.admin)

Consoante as suas autorizações, pode atribuir estas funções a si próprio ou pedir ao seu administrador para as atribuir. Para mais informações sobre a concessão de funções, consulte o artigo Ver as funções atribuíveis aos recursos.

Para ver as autorizações exatas do BigQuery necessárias para consultar tabelas externas, expanda a secção Autorizações necessárias:

Autorizações necessárias

Também pode conseguir estas autorizações com funções personalizadas ou outras funções predefinidas.

Crie e consulte a tabela

Para consultar dados do Bigtable através de uma tabela externa temporária:

A criação e a consulta de uma tabela externa temporária são suportadas pela ferramenta de linhas de comando bq e pela API.

bq

Para consultar uma tabela temporária através de um ficheiro de definição de tabela, introduza o comando bq query com a flag --external_table_definition.

(Opcional) Forneça a flag --location e defina o valor para a sua localização.

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

Substitua o seguinte:

  • LOCATION: o nome da sua localização. A flag --location é opcional.
  • TABLE: o nome da tabela temporária que está a criar.
  • DEFINITION_FILE: o caminho para o ficheiro de definição da tabela no seu computador local.
  • QUERY: a consulta que está a enviar para a tabela temporária.

Por exemplo, o seguinte comando cria e consulta uma tabela temporária denominada follows através de um ficheiro de definição de tabela denominado 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 o artigo Consultar dados para ver informações sobre como criar uma tarefa de consulta.

  • (Opcional) Especifique a sua localização na propriedade location na secção jobReference do recurso de emprego.

  • Especifique as propriedades da origem de dados externa definindo o elemento ExternalDataConfiguration para o recurso de tabela.

Java

Antes de experimentar este exemplo, siga as Javainstruções de configuração no início rápido do BigQuery com bibliotecas cliente. Para mais informações, consulte a API Java BigQuery documentação de referência.

Para se autenticar no BigQuery, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure 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.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 o desempenho

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

  • O número de linhas
  • A quantidade de dados lidos
  • A extensão da paralelização

O BigQuery tenta ler o mínimo de dados possível, lendo apenas as famílias de colunas referenciadas na consulta. A extensão da paralelização depende do número de nós que tem no cluster do Bigtable e do número de divisões que tem para a sua tabela.

Tenha em atenção que o Bigtable une automaticamente as divisões com base na carga. Se a sua tabela não for lida com frequência, haverá menos divisões ao longo do tempo e uma degradação gradual no desempenho das consultas. Para mais informações, consulte o artigo Como o BigQuery otimiza os seus dados ao longo do tempo.

Computação

Quando consulta os seus dados do Bigtable a partir do BigQuery, tem as seguintes opções de computação:

  • Agrupar nós, que é a predefinição.
  • Data Boost (pré-visualização), uma opção de computação sem servidor que lhe permite isolar o tráfego de estatísticas sem afetar o tráfego de publicação de aplicações que os nós dos seus clusters estão a processar.

Para usar o Data Boost, tem de criar um ficheiro de definição que especifique um perfil da app do Data Boost no URI do Bigtable. Para mais informações, consulte o artigo Crie uma tabela externa do Bigtable.

Se não usar o Data Boost, tenha em atenção que a consulta do Bigtable a partir do BigQuery consome ciclos da CPU do Bigtable. O consumo de CPU pelo BigQuery quando usa nós aprovisionados para computação pode afetar a latência e o débito de outros pedidos simultâneos, como a publicação de tráfego de utilizadores em direto. Por exemplo, a utilização elevada da CPU no Bigtable afeta as consultas de cauda longa e aumenta a latência no percentil 99.

Como resultado, deve monitorizar a utilização da CPU do Bigtable para verificar se está dentro dos limites recomendados, conforme indicado no painel de controlo de monitorização do Bigtable na Google Cloud consola. O aumento do número de nós para a sua instância permite-lhe processar o tráfego do BigQuery e o tráfego de outros pedidos simultâneos.

Filtros de consultas

Pode adicionar filtros de consulta quando consulta uma tabela externa para reduzir a utilização de recursos do BigQuery.

Filtro de chave da linha

As consultas com um filtro de igualdade de chave de linha apenas leem essa 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 suportados, mas apenas quando rowkey é lido como uma string com a opção readRowkeyAsString.

Filtre por família de colunas e qualificador

Também pode selecionar uma família de colunas específica ou um qualificador específico numa família de colunas. Para filtrar por família de colunas, selecione o nome da família de colunas. O resultado inclui apenas a família de colunas selecionada. No exemplo seguinte, user_info representa uma família de colunas:

    SELECT
      rowkey AS user_id,
      user_info
    FROM
      project.dataset.table;
Para filtrar por um qualificador específico, primeiro tem de declará-lo em "columns" na definição da tabela externa:
CREATE OR REPLACE EXTERNAL TABLE project.dataset.table
  OPTIONS (
    format = 'CLOUD_BIGTABLE',
    uris = ['https://googleapis.com/bigtable/projects/…/instances/…/tables/…'],
    bigtable_options = '''{
  "columnFamilies": [
    {
      "familyId": "user_info",
      "columns": [
        {
          "qualifierString": "name"
        },
        {
          "qualifierString": "email"
        },
        {
          "qualifierString": "registered_at"
        }
      ]
    },
    {
      "familyId": "session_data"
    }
  ],
  "readRowkeyAsString": true,
  "timestampSuffix": "_ts"
}'''
  );

Depois de criar a tabela externa, use uma declaração SELECT para consultar um qualificador específico. Isto garante que o BigQuery envia o filtro para o Bigtable e carrega apenas os qualificadores especificados quando executa uma declaração SELECT a partir do BigQuery, e não os dados de toda a família de colunas. Isto reduz o consumo de recursos do BigQuery.

    SELECT
      rowkey AS user_id,
      user_info.email.cell[SAFE_OFFSET(0)].value as email
    FROM
      project.dataset.table;