Créer une table externe Bigtable

Cette page explique comment créer une table externe permanente BigQuery qui peut être utilisée pour interroger des données stockées dans Bigtable. L'interrogation des données Bigtable est disponible dans tous les emplacements Bigtable.

Avant de commencer

Avant de créer une table externe, rassemblez certaines informations et assurez-vous de disposer des autorisations nécessaires pour créer la table.

Rôles requis

Pour créer une table externe à utiliser pour interroger vos données Bigtable, vous devez être un compte principal dans le rôle d'administrateur Bigtable (roles/bigtable.admin) pour l'instance contenant la table source.

Vous devez également disposer de l'autorisation Identity and Access Management (IAM) BigQuery bigquery.tables.create.

Tous les rôles Identity and Access Management prédéfinis suivants incluent cette autorisation :

  • Éditeur de données BigQuery (roles/bigquery.dataEditor)
  • Propriétaire de données BigQuery (roles/bigquery.dataOwner)
  • Administrateur BigQuery (roles/bigquery.admin)

Si vous ne disposez pas de compte principal pour l'un de ces rôles, demandez à votre administrateur de vous accorder l'accès ou de créer la table externe à votre place.

Pour en savoir plus sur les rôles et les autorisations Identity and Access Management dans BigQuery, consultez la page Rôles et autorisations prédéfinis. Pour afficher les informations concernant les autorisations Bigtable, consultez la page Contrôle des accès avec Identity and Access Management.

Créer ou identifier un ensemble de données

Avant de créer une table externe, vous devez créer un ensemble de données pour contenir la table externe. Vous pouvez également utiliser un ensemble de données existant.

Facultatif : Désigner ou créer un cluster

Si vous envisagez d'interroger fréquemment les mêmes données que celles utilisées par votre application de production, nous vous recommandons de désigner un cluster de votre instance Bigtable qui ne sera utilisé que pour l'analyse BigQuery. Cela isole le trafic du ou des clusters que vous utilisez pour les lectures et les écritures de votre application. Pour en savoir plus sur la réplication et la création d'instances comportant plusieurs clusters, consultez la page À propos de la réplication.

Identifier ou créer un profil d'application

Avant de créer une table externe, choisissez le profil d'application Bigtable que BigQuery doit utiliser pour lire les données. Nous vous recommandons d'utiliser un profil d'application que vous n'utilisez que pour BigQuery.

Si vous disposez dans votre instance Bigtable d'un cluster dédié à l'accès à BigQuery, configurez le profil d'application pour qu'il utilise le routage à cluster unique vers ce cluster.

Pour en savoir plus sur le fonctionnement des profils d'application Bigtable, consultez la page À propos des profils d'application. Pour savoir comment créer un profil d'application, consultez la section Créer et configurer des profils d'application.

Récupérer l'URI Bigtable

Pour créer une table externe destinée à une source de données Bigtable, vous devez fournir l'URI Bigtable. Pour récupérer l'URI Bigtable, procédez comme suit :

  1. Ouvrez la page Bigtable dans la console.

    Accéder à Bigtable

  2. Récupérez les informations suivantes concernant votre source de données Bigtable :

    • L'ID de votre projet
    • ID de votre instance Bigtable
    • ID du profil d'application Bigtable que vous prévoyez d'utiliser
    • Nom de votre table Bigtable
  3. Composez l'URI Bigtable en utilisant le format ci-dessous, où :

    • project_id correspond au projet contenant votre instance Bigtable
    • instance_id est l'ID de l'instance Bigtable
    • (Facultatif) app_profile est l'ID du profil d'application que vous souhaitez utiliser.
    • table_name est le nom de la table que vous interrogez

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

Créer des tables externes permanentes

Lorsque vous créez une table externe permanente dans BigQuery qui est associée à une source de données Bigtable, vous disposez de deux options pour spécifier le format de la table externe :

  • Si vous utilisez l'API ou l'outil de ligne de commande bq, vous créez un fichier de définition de table qui spécifie le schéma et les métadonnées de la table externe.
  • Si vous utilisez SQL, vous utilisez l'option uri de l'instruction CREATE EXTERNAL TABLE pour spécifier la table Bigtable à partir de laquelle extraire les données, et l'option bigtable_options pour spécifier le schéma de la table.

Les données de la table externe ne sont pas stockées dans la table BigQuery. La table étant permanente, vous pouvez utiliser des contrôles d'accès au niveau de l'ensemble de données pour la partager avec d'autres utilisateurs ayant également accès à la source de données Bigtable sous-jacente.

Pour créer une table permanente, choisissez l'une des méthodes suivantes.

SQL

Vous pouvez créer une table externe permanente en exécutant l'instruction LDD CREATE EXTERNAL TABLE. Vous devez spécifier explicitement le schéma de la table dans les options de l'instruction.

  1. Dans la console Google Cloud, accédez à la page BigQuery.

    Accéder à BigQuery

  2. Dans l'éditeur de requête, saisissez l'instruction suivante :

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

    Remplacez les éléments suivants :

    • DATASET : ensemble de données dans lequel créer la table externe Bigtable.
    • NEW_TABLE : nom de la table externe Bigtable.
    • URI : URI de la table Bigtable que vous souhaitez utiliser comme source de données. Cet URI doit respecter le format décrit dans la section Récupérer l'URI Bigtable.
    • BIGTABLE_OPTIONS : schéma de la table Bigtable au format JSON. Pour obtenir la liste des options de définition de table Bigtable, reportez-vous à la section BigtableOptions dans la documentation de référence de l'API REST.

  3. Cliquez sur Exécuter.

Pour en savoir plus sur l'exécution des requêtes, consultez Exécuter une requête interactive.

Une instruction permettant de créer une table Bigtable externe peut ressembler à ceci :

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

Vous créez une table dans l'outil de ligne de commande bq à l'aide de la commande bq mk. Lorsque vous utilisez l'outil de ligne de commande bq pour créer une table associée à une source de données externe, vous devez identifier le schéma de la table à l'aide d'un fichier de définition de table.

  1. Utilisez la commande bq mk pour créer une table permanente.

    bq mk \
    --external_table_definition=DEFINITION_FILE \
    DATASET.TABLE

    Remplacez les éléments suivants :

    • DEFINITION_FILE : chemin d'accès au fichier de définition de table sur votre ordinateur local.
    • DATASET : nom de l'ensemble de données contenant la table.
    • TABLE : nom de la table que vous créez.

API

Utilisez la méthode API tables.insert, puis créez un objet ExternalDataConfiguration dans laTable de ressource que vous transmettez.

Pour la propriété sourceUris dans la ressource Table, spécifiez un seul URI Bigtable. Il doit s'agir d'une URL HTTPS valide.

Pour la propriété sourceFormat, spécifiez "BIGTABLE".

Java

Avant d'essayer cet exemple, suivez les instructions de configuration pour Java du guide de démarrage rapide de BigQuery : Utiliser les bibliothèques clientes. Pour en savoir plus, consultez la documentation de référence de l'API BigQuery pour Java.

Pour vous authentifier auprès de BigQuery, configurez le service Identifiants par défaut de l'application. Pour en savoir plus, consultez la page Configurer l'authentification pour les bibliothèques clientes.

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

Interroger des tables externes

Pour en savoir plus, consultez la page Interroger des données Bigtable.

Schéma généré

Par défaut, BigQuery expose les valeurs d'une famille de colonnes sous la forme d'un tableau de colonnes contenant lui-même un tableau de valeurs écrites à différents horodatages. Ce schéma conserve la disposition naturelle des données dans Bigtable. Toutefois, l'exécution des requêtes SQL peut s'avérer problématique. Vous pouvez convertir des colonnes en sous-champs dans la famille de colonnes parente et ne lire que la dernière valeur de chaque cellule. Les deux tableaux sont représentés dans le schéma par défaut sous la forme de valeurs scalaires.

Exemple

Vous enregistrez des profils utilisateur pour un réseau social fictif. Un modèle de données applicable à ce cas de figure peut se présenter sous la forme d'une famille de colonnes profile incluant des colonnes pour le genre (gender), l'âge (age) et l'adresse e-mail (email).

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

À partir du schéma par défaut, vous pouvez créer une requête GoogleSQL permettant de comptabiliser les utilisateurs de genre masculin de plus de 30 ans :

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)

Il est plus facile d'interroger les données si les colonnes gender et age sont présentées sous la forme de sous-champs. Pour les présenter de cette façon, répertoriez gender et age sous la forme de colonnes nommées dans la famille de colonnes profile lors de la définition de la table. Vous pouvez également demander à BigQuery de présenter les dernières valeurs de cette famille de colonnes, car seule la dernière valeur présente un intérêt. Il peut également s'agir de la seule valeur disponible.

Une fois que les colonnes sont présentées sous la forme de sous-champs, la requête GoogleSQL permettant de comptabiliser les utilisateurs de genre masculin de plus de 30 ans se présente comme suit :

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

Notez que les colonnes gender et age sont référencées directement sous forme de champs. La configuration JSON correspondant à ce cas de figure est la suivante :

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

Encodage de valeurs

Bigtable stocke les données sous forme d'octets bruts, indépendamment de l'encodage. Toutefois, les valeurs de type octet sont d'une utilité limitée pour l'analyse des requêtes SQL. Bigtable fournit deux types élémentaires de décodage scalaire : texte et binaire HBase.

Dans le format texte, on part du principe que toutes les valeurs sont stockées sous la forme de chaînes de texte alphanumériques. Par exemple, l'entier 768 correspond à la chaîne "768". Dans l'encodage binaire, on considère que la classe de méthodes HBase Bytes.toBytes a été utilisée pour encoder les données et qu'elle applique une méthode de décodage appropriée.

Régions et zones disponibles

L'interrogation des données Bigtable est disponible dans toutes les zones Bigtable compatibles. Vous trouverez la liste des zones sur cette page. Pour les instances multiclusters, BigQuery achemine le trafic en fonction des paramètres du profil d'application Bigtable.

Limites

Pour en savoir plus sur les limites applicables aux tables externes, consultez la section Limites des tables externes.

Champs d'application des instances Compute Engine

Lorsque vous créez une instance Compute Engine, vous pouvez spécifier une liste de champs d'application pour celle-ci. Les champs d'application contrôlent l'accès de l'instance aux produits Google Cloud, y compris Bigtable. Les applications exécutées sur la VM utilisent le compte de service pour appeler les API Google Cloud.

Si vous configurez une instance Compute Engine pour qu'elle s'exécute en tant que compte de service et que ce compte accède à une table externe associée à une source de données Bigtable, vous devez ajouter à l'instance le champ d'application Bigtable permettant un accès en lecture seule aux données (https://www.googleapis.com/auth/bigtable.data.readonly). Pour en savoir plus, consultez la page Créer une instance Compute Engine pour Bigtable.

Pour en savoir plus sur l'attribution de champs d'application à une instance Compute Engine, consultez la section Modifier le compte de service et les champs d'application d'accès d'une instance. Pour en savoir plus sur les comptes de service Compute Engine, consultez la page Comptes de service.

Étapes suivantes