Consulta datos de Cloud Bigtable

En esta página, se describe cómo usar BigQuery para consultar datos almacenados en Cloud Bigtable.

Cloud 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. Cloud Bigtable tiene un modelo de datos similar a Apache HBase y proporciona una biblioteca cliente compatible con HBase. Para obtener más información sobre el modelo de datos de Cloud Bigtable, consulta Modelo de almacenamiento.

Regiones y zonas compatibles

Por el momento, la consulta de datos en Cloud Bigtable está disponible solo en las regiones y zonas siguientes:
Región Zonas
us-central1

us-central1-a

us-central1-b

us-central1-c

us-central1-f

europe-west1

europe-west1-b

europe-west1-c

europe-west1-d

Recupera el URI de Cloud Bigtable

Con el fin de crear una tabla externa para una fuente de datos de Cloud Bigtable, tienes que proporcionar el URI de Cloud Bigtable. Si quieres recuperar el URI de Cloud Bigtable, sigue estos pasos:

  1. Abre la consola de Cloud Bigtable.

    Abrir la consola de Cloud Bigtable

  2. Recupera los detalles siguientes sobre tu fuente de datos de Cloud Bigtable:

    • Tu ID del proyecto
    • Tu ID de instancia de Cloud Bigtable
    • El nombre de tu tabla de Cloud Bigtable
  3. Redacta el URI de Cloud Bigtable con el formato que se muestra a continuación, en el que se ilustra lo siguiente:

    • project_id es el proyecto que contiene tu instancia de Cloud Bigtable.
    • instance_id es el ID de la instancia de Cloud Bigtable.
    • table_name es el nombre de la tabla que deseas consultar.

    https://googleapis.com/bigtable/projects/project_id/instances/instance_id/tables/table_name

Controles de acceso y alcances

Controles de acceso para tablas externas permanentes

Puedes compartir el acceso a una tabla externa permanente vinculada a una fuente de datos de Cloud Bigtable. No puedes compartir acceso a una tabla externa temporal.

Puedes compartir acceso a una tabla externa permanente con usuarios (incluso a cuentas de servicio) o grupos. Para consultar la tabla externa, tus usuarios o grupos necesitan (como mínimo) lo siguiente:

  • La función bigquery.dataViewer a nivel del conjunto de datos o superior para acceder al conjunto de datos que contiene la tabla externa
  • La función bigquery.user a nivel de proyecto o superior para ejecutar trabajos de consulta
  • La función bigtable.reader en Cloud Bigtable, que proporciona acceso de solo lectura a metadatos y tablas

Alcances para instancias de Compute Engine

Cuando creas una instancia de Compute Engine, puedes especificar una lista de alcances para la instancia. Los alcances controlan el acceso de la instancia a los productos de Google Cloud, incluido Cloud Bigtable. Las aplicaciones que se ejecutan en la VM usan la cuenta de servicio para llamar a las API de Google Cloud.

Si configuras una instancia de Compute Engine para que se ejecute como cuenta de servicio y esta accede a una tabla externa vinculada a una fuente de datos de Cloud Bigtable, debes agregar el nivel de acceso de datos de solo lectura de Cloud Bigtable (https://www.googleapis.com/auth/bigtable.data.readonly) a la instancia. Si deseas obtener más información, consulta la página sobre cómo crear una instancia de Compute Engine para Cloud Bigtable.

Para obtener más información acerca de cómo aplicar alcances a una instancia de Compute Engine, consulta la página sobre cómo cambiar la cuenta de servicio y los niveles de acceso de una instancia. Para obtener más información sobre las cuentas de servicio de Compute Engine, consulta la sección sobre las cuentas de servicio.

Tablas externas permanentes y temporales

Puedes consultar una fuente de datos externa en BigQuery; para ello, usa una tabla permanente o una temporal. Una tabla permanente es una tabla que se crea en un conjunto de datos y está vinculada a tu fuente de datos externa. Debido a que la tabla es permanente, puedes usar controles de acceso para compartir la tabla con otras personas que también tengan acceso a la fuente de datos externa subyacente y también puedes hacer consultas en cualquier momento.

Cuando consultas una fuente de datos externa con una tabla temporal, envías un comando que incluye una consulta y crea una tabla no permanente vinculada a la fuente de datos externa. Cuando usas una tabla temporal, no se crea una tabla en uno de tus 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. 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).

Consulta datos de Cloud Bigtable con tablas externas permanentes

Para consultar una fuente de datos de Cloud Bigtable por medio de una tabla permanente, debes crear una tabla en un conjunto de datos de BigQuery vinculado a tu fuente de datos de Cloud Bigtable. Los datos no se almacenan en la tabla de BigQuery. Debido a que la tabla es permanente, puedes usar controles de acceso a nivel de conjunto de datos para compartirla con otras personas que también tienen acceso a la fuente de datos subyacente de Cloud Bigtable.

Cuando creas una tabla externa permanente en BigQuery vinculada a una fuente de datos de Cloud Bigtable, hay dos formas de especificar el esquema de la tabla:

  • Si usas la API o la herramienta de línea de comandos de bq, crea un archivo de definición de tablas que defina el esquema y los metadatos para la fuente de datos externa.
  • Si usas Cloud Console, ingresa la familia de columnas y los calificadores de Cloud Bigtable de forma manual.

Para consultar los datos de Cloud Bigtable mediante una tabla externa permanente, sigue estos pasos:

  • Crea un archivo de definición de tablas (para la API o la herramienta de línea de comandos de bq).
  • Crea una tabla en BigQuery vinculada a la fuente de datos externa.
  • Consulta los datos con la tabla permanente.

Crea y consulta una tabla externa permanente

Con el fin de crear y consultar una tabla externa permanente, sigue estos pasos:

Console

Por el momento, no es posible consultar datos de Cloud Bigtable con Cloud Console.

bq

Debes crear una tabla en la herramienta de línea de comandos de bq mediante el comando bq mk. Cuando usas la herramienta de línea de comandos de bq para crear una tabla vinculada a una fuente de datos externa, puedes identificar el esquema de la tabla mediante un archivo de definición de tablas.

  1. Usa el comando bq mk para crear una tabla permanente.

    bq mk \
    --external_table_definition=definition_file \
    dataset.table
    

    Aquí:

    • definition_file es la ruta de acceso al archivo de definición de tabla en tu máquina local.
    • dataset es el nombre del conjunto de datos que contiene la tabla.
    • table es el nombre de la tabla que creas.

    Luego, puedes ejecutar una consulta en la tabla como si fuera una tabla nativa de BigQuery, sujeta a las limitaciones para las fuentes de datos externas.

API

  • Para la propiedad sourceUris en el recurso de tabla, puedes especificar un URI de Cloud Bigtable, y debe ser una URL de HTTPS validada y especificada por completo.

  • Especifica las propiedades del formato de datos mediante la configuración de la propiedad sourceFormat. En Cloud Bigtable, especifica "BIGTABLE".

Java

Antes de probar este ejemplo, sigue las instrucciones de configuración para Java que se encuentran 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.

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

Consulta datos de Cloud Bigtable con tablas externas temporales

Si quieres realizar una consulta sobre una fuente de datos externa sin crear una tabla permanente, debes ejecutar un comando que combine lo siguiente:

  • Un archivo de definición de tablas con una consulta
  • Una definición de esquema intercalado con una consulta
  • Un archivo de definición de esquema JSON con una consulta

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. La herramienta de línea de comandos de bq y la API admiten las consultas a una fuente de datos externa mediante el uso de una tabla temporal.

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. 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).

Crea y consulta una tabla externa temporal

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

Por el momento, 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'

Aquí:

  • location es el nombre de tu ubicación. La marca --location es opcional.
  • table es el nombre de la tabla temporal que creas.
  • definition_file es la ruta de acceso al archivo de definición de tabla de 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 tabla 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 que se encuentran 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.

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 de rendimiento

El rendimiento de las consultas en las fuentes de datos externas de Cloud 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 Cloud Bigtable y cuántas divisiones tengas para tu tabla.

Ten en cuenta que Cloud 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 Cloud Bigtable desde BigQuery consume ciclos de CPU de Cloud 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 de cola larga y aumenta la latencia al percentil 99.

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

Esquema generado

De forma predeterminada, BigQuery expone los valores en una familia de columnas como un arreglo de columnas y, dentro de eso, un arreglo de valores escrito en marcas de tiempo diferentes. En este esquema, se conserva el diseño natural de los datos en Cloud Bigtable, pero las consultas de SQL pueden ser desafiantes. Es posible promover columnas a subcampos dentro de la familia de columnas superior y leer solo el valor actual de cada celda. Esto representa ambos arreglos en el esquema predeterminado como valores escalares.

Ejemplo

Aquí, almacenarás perfiles del usuario para una red social ficticia. Un modelo de datos sería una familia de columnas profile con columnas individuales para gender, age y, también, email:

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

Con el esquema predeterminado, esta es una consulta de SQL estándar para contar el número de usuarios masculinos de más de 30 años:

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)

La consulta de los datos es menos complicada si gender y age se exponen como subcampos. Para exponerlos como subcampos, enumera gender y age como columnas con nombre en la familia de columnas profile cuando definas la tabla. También, puedes indicar a BigQuery que exponga los valores más recientes de esta familia de columnas desde entonces. Por lo general, solo el valor más reciente (y posiblemente el único) es de interés.

Después de exponer las columnas como subcampos, esta es la consulta de SQL estándar para contar el número de usuarios masculinos por encima de los 30 años:

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

Ten en cuenta cómo se hace referencia a gender y age como campos de forma directa. Para este caso, la configuración de JSON es la que se muestra a continuación:

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

Codificación de valor

Cloud Bigtable almacena datos como bytes sin procesar, independiente de la codificación de los datos. Sin embargo, los valores de bytes son de uso limitado en los análisis de consultas de SQL. Cloud Bigtable proporciona dos tipos básicos de decodificación escalar: texto y objeto binario HBase.

El formato de texto presupone que todos los valores se almacenan como strings de texto alfanumérico. Por ejemplo, un número entero 768 se almacenará como la string “768”. Con la codificación binaria, se da por sentado que las clases de métodos Bytes.toBytes de HBase se usaron para codificar los datos y se aplica un método de decodificación apropiado.

Filtros de consulta

Las consultas con un filtro de igualdad de fila solo leen esa fila específica. Por ejemplo, en la sintaxis de SQL estándar, 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.