Consulta datos de Bigtable

En este documento, se describe cómo consultar datos almacenados en una tabla externa de Bigtable.

Bigtable es la base de datos NoSQL poco poblada de Google que puede escalar a miles de millones de filas, miles de columnas y petabytes de datos. Para obtener más información sobre el modelo de datos de Bigtable, consulta Modelo de almacenamiento.

Consulta tablas externas permanentes

Antes de comenzar, tú o alguien de tu organización deben crear una tabla externa para que la uses. Para obtener detalles y permisos necesarios, consulta Crea una tabla externa de BigQuery.

Roles obligatorios

Para consultar tablas externas permanentes de Bigtable, asegúrate de tener los siguientes roles:

  • Visualizador de datos de BigQuery (roles/bigquery.dataViewer)
  • Usuario de BigQuery (roles/bigquery.user)
  • Lector de Bigtable (roles/bigtable.reader)

Según los permisos que tengas, puedes otorgarte estos roles o pedirle a tu administrador que te los otorgue. Para obtener más información sobre cómo otorgar roles, consulta Visualiza los roles que se pueden otorgar en los recursos.

A fin de ver los permisos exactos de BigQuery que se requieren para consultar tablas externas, expande la sección Permisos necesarios:

Permisos necesarios

También puedes obtener estos permisos con roles personalizados o con otros roles predefinidos.

Consulte la tabla

Puedes ejecutar una consulta en una tabla de Bigtable externa permanente exactamente como si fuera una tabla estándar de BigQuery, sujeta a las limitaciones sobre fuentes de datos externas. Para obtener más información, consulta Ejecuta consultas interactivas y por lotes.

Consulta tablas externas temporales

Consultar una fuente de datos externa con una tabla temporal es útil para las consultas únicas ad-hoc sobre datos externos o procesos de extracción, transformación y carga (ETL).

Para consultar una fuente de datos externa sin crear una tabla permanente, debes proporcionar una definición de tabla para la tabla temporal y, luego, usar esa definición de tabla en un comando o llamada para consultar la tabla temporal. Puedes proporcionar la definición de la tabla de cualquiera de las siguientes maneras:

Se emplea el archivo de definición de tabla o el esquema proporcionado para crear la tabla externa temporal, y es en esta donde se ejecuta la consulta.

Cuando usas una tabla externa temporal, no se crea una tabla en uno de los conjuntos de datos de BigQuery. Debido a que la tabla no se almacena de forma permanente en un conjunto de datos, no puede compartirse con otras personas.

El uso de una tabla externa temporal en lugar de una tabla externa permanente tiene algunas limitaciones, incluidas las siguientes:

  • Debes tener la función de administrador de Bigtable (roles/bigtable.admin).
  • Este enfoque no te permite usar la consola de Google Cloud para inferir el esquema de la tabla de Bigtable y crear la definición de tablas de forma automática. Debes crear la definición de tabla tú mismo.

Roles obligatorios

Para consultar tablas externas temporales de Bigtable, asegúrate de tener los siguientes roles:

  • Visualizador de datos de BigQuery (roles/bigquery.dataViewer)
  • Usuario de BigQuery (roles/bigquery.user)
  • Administrador de Bigtable (roles/bigtable.admin)

Según los permisos que tengas, puedes otorgarte estos roles o pedirle a tu administrador que te los otorgue. Para obtener más información sobre cómo otorgar roles, consulta Visualiza los roles que se pueden otorgar en los recursos.

A fin de ver los permisos exactos de BigQuery que se requieren para consultar tablas externas, expande la sección Permisos necesarios:

Permisos necesarios

También puedes obtener estos permisos con roles personalizados o con otros roles predefinidos.

Crea y consulta la tabla

Para consultar los datos de Bigtable mediante una tabla temporal externa, debes realizar lo siguiente:

La creación de una tabla externa temporal y las consultas a ella son compatibles con la herramienta de línea de comandos de bq y la API.

bq

Para realizar una consulta en una tabla temporal con un archivo de definición de tablas, ingresa el comando bq query con la marca --external_table_definition.

Opcional: Proporciona la marca --location y configura el valor en tu ubicación.

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

Reemplaza lo siguiente:

  • LOCATION: El nombre de tu ubicación. La marca --location es opcional.
  • TABLE: Es el nombre de la tabla temporal que crearás.
  • DEFINITION_FILE: es la ruta de acceso al archivo de definición de tabla en tu máquina local.
  • QUERY: es la consulta que enviarás a la tabla temporal.

Por ejemplo, con el siguiente comando, se crea y consulta una tabla temporal llamada follows mediante un archivo de definición de tablas denominado follows_def.

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

API

  • Crea una consulta. Visita la página sobre cómo consultar datos para obtener información acerca de cómo crear un trabajo de consulta.

  • Especifica tu ubicación en la propiedad location en la sección jobReference del recurso del trabajo (opcional).

  • Especifica las propiedades de la fuente de datos externa mediante la configuración de ExternalDataConfiguration para el recurso de tabla.

Java

Antes de probar este ejemplo, sigue las instrucciones de configuración para Java incluidas en la guía de inicio rápido de BigQuery sobre cómo usar bibliotecas cliente. Para obtener más información, consulta la documentación de referencia de la API de BigQuery para Java.

Para autenticarte en BigQuery, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para bibliotecas 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());
    }
  }
}

Consideraciones sobre el rendimiento

El rendimiento de las consultas en las fuentes de datos externas de Bigtable depende de tres factores:

  • El número de filas
  • La cantidad de datos leídos
  • La extensión de la paralelización

BigQuery intenta leer la menor cantidad de datos posible y solo leer las familias de columnas referenciadas en la consulta. El alcance de la paralelización depende de la cantidad de nodos que tengas en tu clúster de Bigtable y cuántas divisiones tengas para tu tabla.

Ten en cuenta que Bigtable fusiona de forma automática las divisiones según la carga. Si tu tabla no se lee con frecuencia, con el tiempo, habrá menos divisiones y una degradación gradual en el rendimiento de la consulta. Para obtener más información sobre cómo dividir una tabla por clave de fila, consulta Administra tablas.

Consultar Bigtable desde BigQuery consume ciclos de CPU de Bigtable. El consumo de CPU por parte de BigQuery puede afectar la latencia y capacidad de procesamiento de otras solicitudes simultáneas, como la entrega de tráfico de usuarios en vivo. Por ejemplo, un uso alto de CPU en Cloud Bigtable afecta las consultas finales y aumenta la latencia al percentil 99.

Debes supervisar el uso de CPU de Bigtable para verificar que te encuentres dentro de los límites recomendados, como se indica en el panel de supervisión de Bigtable en la consola de Google Cloud. Aumentar el número de nodos para tu instancia te permite controlar el tráfico de BigQuery y el tráfico de otras solicitudes simultáneas.

Filtros de consulta

Las consultas con un filtro de igualdad de fila solo leen esa fila específica. Por ejemplo, en la sintaxis de GoogleSQL, se observa lo siguiente:

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

Los filtros de rango, como rowkey > '1' y rowkey < '8', también son compatibles, pero solo cuando la clave de fila se lee como una string con la opción readRowkeyAsString.