Crea una tabla externa de Bigtable

En esta página, se describe cómo crear una tabla externa permanente de BigQuery que puede usarse para consultar datos almacenados en Bigtable. La consulta de datos en Bigtable está disponible en todas las ubicaciones de Bigtable.

Antes de empezar

Antes de crear una tabla externa, recopila información y asegúrate de tener permiso para crear la tabla.

Roles obligatorios

A fin de crear una tabla externa que se use para consultar tus datos de Bigtable, debes ser una principal en el rol Administrador de Bigtable (roles/bigtable.admin) para la instancia que contiene la tabla de origen.

También necesitas el permiso bigquery.tables.create de BigQuery Identity and Access Management (IAM).

Cada una de los siguientes roles predefinidos de Identity and Access Management incluye este permiso:

  • Editor de datos de BigQuery (roles/bigquery.dataEditor)
  • Propietario de datos de BigQuery (roles/bigquery.dataOwner)
  • BigQuery Admin (roles/bigquery.admin)

Si no eres principal en estos roles, pídele a tu administrador que te otorgue acceso o que cree la tabla externa por ti.

Para obtener más información sobre las funciones y los permisos de la administración de identidades y accesos en BigQuery, consulta Funciones y permisos predefinidos. Para obtener información sobre los permisos de Bigtable, consulta Control de acceso con Identity and Access Management.

Crea o identifica un conjunto de datos

Antes de crear una tabla externa, debes crear un conjunto de datos para contener la tabla. También puedes usar un conjunto de datos existente.

Opcional: Designa o crea un clúster

Si planeas consultar con frecuencia los mismos datos que entregan tu aplicación de producción, te recomendamos que designes un clúster en tu instancia de Bigtable para que se use solo con el análisis de BigQuery. Esto aísla el tráfico de los clústeres que usas para las lecturas y escrituras de tu aplicación. Para obtener más información sobre la replicación y la creación de instancias que tengan más de un clúster, consulta Información sobre la replicación.

Identifica o crea un perfil de app

Antes de crear una tabla externa, decide qué perfil de app de Bigtable debería usar BigQuery para leer los datos. Te recomendamos que uses un perfil de aplicación que designes solo para usarlo con BigQuery.

Si tienes un clúster en tu instancia de Bigtable dedicado al acceso a BigQuery, configura el perfil de la app para que use el enrutamiento de un solo clúster a ese clúster.

Para obtener información sobre cómo funcionan los perfiles de app de Bigtable, consulta Acerca de los perfiles de app. Para obtener información sobre cómo crear un perfil de app nuevo, consulta Crea y configura perfiles de app.

Recupera el URI de Bigtable

Con el fin de crear una tabla externa para una fuente de datos de Bigtable, debes proporcionar el URI de Bigtable. Para recuperar el URI de Bigtable, haz lo siguiente:

  1. Abre la página de Bigtable en la consola.

    Ir a Bigtable

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

    • Tu ID del proyecto
    • Tu ID de instancia de Bigtable
    • El ID del perfil de app de Bigtable que planeas usar
    • El nombre de tu tabla de Bigtable
  3. Redacta el URI de Bigtable mediante el siguiente formato, en el que se dan las siguientes situaciones:

    • project_id es el proyecto que contiene tu instancia de Bigtable.
    • instance_id es el ID de la instancia de Bigtable
    • (Opcional) app_profile es el ID del perfil de la app que deseas usar.
    • table_name es el nombre de la tabla que consultas.

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

Crea tablas externas permanentes

Cuando creas una tabla externa permanente en BigQuery vinculada a una fuente de datos de Bigtable, hay dos opciones para especificar el formato de la tabla externa:

  • 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 tabla externa.
  • Si usas SQL, usa la opción uri de la declaración CREATE EXTERNAL TABLE a fin de especificar la tabla de Bigtable para extraer datos y la opción bigtable_options a fin de especificar el esquema de la tabla.

Los datos de la tabla externa 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 Bigtable.

Para crear una tabla permanente, elige uno de los siguientes métodos.

SQL

Puedes crear una tabla externa permanente si ejecutas la instrucción de DDL CREATE EXTERNAL TABLE. Debes especificar el esquema de tabla de forma explícita como parte de las opciones de la declaración.

  1. En la consola de Google Cloud, ve a la página de BigQuery.

    Ir a BigQuery

  2. En el editor de consultas, escribe la siguiente oración:

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

    Reemplaza lo siguiente:

    • DATASET: Es el conjunto de datos en el que se creará la tabla externa de Bigtable.
    • NEW_TABLE: Es el nombre de la tabla externa de Bigtable.
    • URI: El URI de la tabla de Bigtable que deseas usar como fuente de datos. Este URI debe seguir el formato que se describe en Recupera el URI de Bigtable.
    • BIGTABLE_OPTIONS: Es el esquema para la tabla de Bigtable en formato JSON. Para obtener una lista de las opciones de definición de tablas de Bigtable, consulta BigtableOptions en la referencia de la API de REST.

  3. Haz clic en Ejecutar.

Si deseas obtener información sobre cómo ejecutar consultas, visita Ejecuta una consulta interactiva.

Una instrucción para crear una tabla de Bigtable externa podría ser similar a la que se muestra a continuación:

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

Debes crear una tabla en la herramienta de línea de comandos de bq con 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

    Reemplaza lo siguiente:

    • 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 crearás.

API

Usa el método de API tables.insert y crea un ExternalDataConfiguration en el Table recurso que pasas.

Para la propiedad sourceUris en el recurso Table, especifica solo un URI de Bigtable. Debe ser una URL HTTPS válida.

En la propiedad sourceFormat, especifica "BIGTABLE".

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.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 tablas externas

Para obtener más información, visita Consulta datos de Bigtable.

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 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 GoogleSQL 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 porque, 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 GoogleSQL 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

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

Regiones y zonas compatibles

La consulta de datos en Bigtable está disponible en todas las zonas de Bigtable compatibles. Puedes encontrar la lista de zonas aquí. Para instancias de varios clústeres, BigQuery enruta el tráfico según la configuración de perfil de la aplicación de Bigtable.

Limitaciones

Para obtener información sobre las limitaciones que se aplican a las tablas externas, consulta Limitaciones de las tablas externas.

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 Bigtable. Las aplicaciones que se ejecutan en la VM usan la cuenta de servicio para llamar a las APIs 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 Bigtable, debes agregar el nivel de acceso de datos de solo lectura de 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 Bigtable.

Para obtener más información acerca de cómo aplicar alcances a una instancia de Compute Engine, consulta Cambia 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.

¿Qué sigue?