Créer et utiliser des tables en cluster

Ce document décrit comment créer et utiliser des tables en cluster dans BigQuery. Pour une présentation de la disponibilité des tables en cluster dans BigQuery, consultez la page Présentation des tables en cluster.

Limites

Les tables en cluster dans BigQuery sont soumises aux limitations suivantes :

  • Le clustering n'est disponible que pour les tables partitionnées.
  • Seul le langage SQL standard est compatible avec l'interrogation de tables en cluster et avec l'écriture des résultats de requête dans des tables en cluster.
  • Il n'est possible de spécifier que des colonnes de clustering lors de la création d'une table.
  • Une fois une table en cluster créée, vous ne pouvez pas modifier les colonnes de clustering.
  • Les colonnes de clustering doivent être des colonnes uniques de premier niveau, de l'un des types suivants :

    • DATE
    • BOOL
    • GEOGRAPHY
    • INT64
    • NUMERIC
    • STRING
    • TIMESTAMP

    Pour en savoir plus sur les types de données, consultez la page Types de données du langage SQL standard.

  • Un maximum de quatre colonnes de clustering peut être spécifié.

  • Lorsque vous utilisez des colonnes de type STRING pour le clustering, BigQuery n'utilise que les 1 024 premiers caractères pour mettre en cluster les données. Les valeurs des colonnes peuvent elles-mêmes être supérieures à 1 024.

Créer des tables en cluster

Actuellement, vous ne pouvez mettre en cluster que des tables partitionnées. Cela inclut à la fois les tables partitionnées par date d'ingestion et les tables partitionnées par une colonne TIMESTAMP ou DATE.

Une table en cluster peut être créée dans BigQuery comme suit :

Dénomination des tables

Lorsque vous créez une table dans BigQuery, le nom de la table doit être unique pour chaque ensemble de données. Le nom de la table peut :

  • contenir jusqu'à 1 024 caractères ;
  • contenir des lettres (majuscules ou minuscules), des chiffres et des traits de soulignement.

Autorisations requises

Pour créer une table, vous devez disposer au minimum des autorisations suivantes :

  • Autorisations bigquery.tables.create pour créer la table
  • Autorisations bigquery.tables.updateData pour écrire des données dans la table à l'aide d'une tâche de chargement, de requête ou de copie
  • Autorisations bigquery.jobs.create pour exécuter une tâche de requête, de chargement ou de copie qui écrit des données dans la table

Des autorisations supplémentaires, telles que bigquery.tables.getData, peuvent être nécessaires pour accéder aux données que vous écrivez dans la table.

Les rôles Cloud IAM prédéfinis suivants incluent les autorisations bigquery.tables.create et bigquery.tables.updateData :

  • bigquery.dataEditor
  • bigquery.dataOwner
  • bigquery.admin

Les rôles Cloud IAM prédéfinis suivants incluent les autorisations bigquery.jobs.create :

  • bigquery.user
  • bigquery.jobUser
  • bigquery.admin

En outre, si un utilisateur possède les autorisations bigquery.datasets.create, il obtient également un accès bigquery.dataOwner à l'ensemble de données qu'il crée. L'accès correspondant au rôle bigquery.dataOwner donne à l'utilisateur la possibilité de créer et de mettre à jour des tables dans l'ensemble de données.

Pour en savoir plus sur les rôles et les autorisations Cloud IAM dans BigQuery, consultez la page Rôles et autorisations prédéfinis.

Créer une table en cluster vide avec une définition de schéma

Lors de la création d'une table dans BigQuery, des colonnes de clustering doivent être spécifiées. Une fois la table créée, vous pouvez modifier les colonnes de clustering. Pour en savoir plus, consultez la section Modifier la spécification du clustering. Vous ne pouvez spécifier des colonnes de clustering que pour des tables partitionnées.

Les colonnes de clustering doivent être des colonnes uniques de premier niveau. Elles doivent correspondre à l'un des types de données simples suivants :

  • DATE
  • BOOLEAN
  • GEOGRAPHY
  • INTEGER
  • NUMERIC
  • STRING
  • TIMESTAMP

Un maximum de quatre colonnes de clustering peut être spécifié. Si plusieurs colonnes sont spécifiées, leur ordre détermine l'ordre des données. Par exemple, si la table est mise en cluster selon les colonnes a, b et c, les données sont triées dans le même ordre : la colonne a en premier, puis la colonne b et enfin la colonne c. Il est recommandé de faire apparaître en premier la colonne la plus fréquemment filtrée ou agrégée.

L'ordre des colonnes de clustering affecte également les performances et le tarif des requêtes. Pour en savoir plus sur les bonnes pratiques concernant l'interrogation de tables en cluster, consultez la page Interroger des tables en cluster.

Pour créer une table en cluster vide avec une définition de schéma, procédez comme suit :

Console

  1. Dans Google Cloud Console, accédez à l'UI Web de BigQuery.

    Accéder à l'UI Web de BigQuery

  2. Dans la section Ressources du panneau de navigation, développez votre projet et sélectionnez un ensemble de données.

  3. À droite de la fenêtre, dans le panneau de détails, cliquez sur Créer une table.

    Bouton

  4. Sur la page Créer une table, sous Source, sélectionnez Table vide pour Créer une table à partir de.

    Option

  5. Sous Destination :

    • Pour le champ Nom de l'ensemble de données, sélectionnez l'ensemble de données approprié, puis saisissez le nom de la table que vous créez dans le champ Nom de la table.
    • Vérifiez que Type de table est défini sur Table native.
  6. Sous Schéma, saisissez la définition du schéma.

    • Indiquez manuellement les informations de schéma de l'une des manières suivantes :

      • Activez l'option Modifier sous forme de texte et saisissez le schéma de la table sous forme de tableau JSON.

      • Utilisez l'option Ajouter un champ pour saisir manuellement le schéma.

  7. Sous Paramètres de partitionnement et de clustering, sélectionnez l'option Partitionner par champ, puis choisissez la colonne DATE ou TIMESTAMP. Cette option n'est pas disponible si le schéma ne contient pas de colonne DATE ni TIMESTAMP.

    Pour créer une table partitionnée par date d'ingestion, sélectionnez Partitionner par date d'ingestion.

  8. (Facultatif) Pour le champ Filtre de partitionnement, cochez la case Demander un filtre de partitionnement pour obliger les utilisateurs à inclure une clause WHERE spécifiant les partitions à interroger. Ce type de filtre peut contribuer à réduire les coûts et à améliorer les performances. Pour en savoir plus, consultez la section Interroger des tables partitionnées.

  9. (Facultatif) Pour Ordre de clustering, saisissez entre un et quatre noms de colonnes séparés par des virgules.

  10. (Facultatif) Cliquez sur Options avancées. Pour le champ Chiffrement, cliquez sur Clé gérée par le client pour utiliser une clé Cloud Key Management Service. Si vous conservez le paramètre Clé gérée par Google, BigQuery chiffre les données au repos.

  11. Cliquez sur Créer une table.

UI classique

  1. Accédez à l'UI Web classique de BigQuery.

    Accéder à l'UI Web de BigQuery

  2. Dans le volet de navigation, cliquez sur la flèche vers le bas Flèche vers le bas. à côté du nom de l'ensemble de données, puis sur Créer une table.

  3. Dans la section Données sources de la page Créer une table, cliquez sur Créer une table vide.

  4. Dans la section Table de destination de la page Créer une table :

    • Dans le champ Nom de la table, sélectionnez l'ensemble de données approprié, puis saisissez le nom de la table que vous créez.
    • Vérifiez que Table type (Type de table) est défini sur Native table (Table native).
  5. Dans la section Schema (Schéma), saisissez manuellement la définition du schéma.

    • Vous pouvez saisir les informations du schéma manuellement en utilisant les méthodes suivantes :

      • En cliquant sur Modifier sous forme de texte, puis en saisissant le schéma de la table en tant que tableau JSON

      • En utilisant l'option Ajouter un champ pour saisir le schéma.

  6. Sous Options :

    • Sous Type de partitionnement, cliquez sur Aucun et sélectionnez Jour.
    • Pour Champ de partitionnement, choisissez l'une des options suivantes :
      • Choisissez timestamp pour créer une table partitionnée en fonction d'une colonne DATE ou TIMESTAMP.
      • Sélectionnez _PARTITIONTIME pour créer une table partitionnée par date d'ingestion.
    • Pour Champs de clustering, saisissez un à quatre noms de champs.
    • Pour Chiffrement de la destination, conservez l'option Default. Cette propriété est destinée aux clés de chiffrement gérées par le client. Par défaut, BigQuery chiffre le contenu client stocké au repos.

      Détails des tables partitionnées.

  7. Cliquez sur Créer une table.

Une fois la table créée, vous pouvez mettre à jour le délai d'expiration, la description et les libellés de la table en cluster. Vous ne pouvez pas ajouter de délai d'expiration de la partition après avoir créé une table à l'aide de l'UI Web de BigQuery.

CLI

Exécutez la commande mk avec les options suivantes :

  • --table (ou le raccourci -t).
  • --schema. Vous pouvez fournir la définition de schéma de la table de manière intégrée ou utiliser un fichier de schéma JSON.
  • Soit --time_partitioning_type (pour les tables partitionnées par date d'ingestion), soit --time_partitioning_field (pour les tables partitionnées). Actuellement, DAY est la seule valeur acceptée pour --time_partitioning_type.
  • --clustering_fields. Un maximum de quatre colonnes de clustering peut être spécifié.

Les paramètres facultatifs sont --expiration, --description, --time_partitioning_expiration, --destination_kms_key et --label.

Si vous créez une table dans un projet autre que votre projet par défaut, ajoutez l'ID du projet au nom de l'ensemble de données, en respectant le format suivant : project_id:dataset.

--destination_kms_key n'est pas présenté ici. Pour en savoir plus sur l'utilisation de --destination_kms_key, consultez la page Clés de chiffrement gérées par le client.

Entrez la commande suivante pour créer une table en cluster vide avec une définition de schéma :

bq mk \
--table \
--expiration integer1 \
--schema schema \
--time_partitioning_type=DAY \
--time_partitioning_field partition_column \
--clustering_fields cluster_columns \
--time_partitioning_expiration integer2 \
--description "description" \
--label key:value,key:value \
project_id:dataset.table

Remplacez l'élément suivant :

  • integer1 : durée de vie par défaut (en secondes) de la table. La valeur minimale est de 3 600 secondes (une heure). Le délai d'expiration correspond à l'heure actuelle plus la valeur entière. Si vous définissez le délai d'expiration de la table lorsque vous créez une table partitionnée par temps d'ingestion, le paramètre d'expiration de la table par défaut de l'ensemble de données est ignoré. La définition de cette valeur supprime la table et toutes les partitions après le délai indiqué.
  • schema : définition de schéma intégrée au format column:data_type,column:data_type ou chemin d'accès au fichier de schéma JSON sur votre machine locale.
  • partition_column : nom de la colonne TIMESTAMP ou DATE utilisée pour créer une table partitionnée. Si vous créez une table partitionnée, vous n'avez pas besoin de spécifier l'option --time_partitioning_type=DAY.
  • cluster_columns : liste de quatre colonnes de clustering au maximum, séparées par des virgules.
  • integer2 : durée de vie par défaut (en secondes) des partitions de la table. Il n'y a pas de valeur minimale. Le délai d'expiration correspond à la date de la partition plus la valeur entière. Le délai d'expiration de la partition est indépendant du délai d'expiration de la table, mais il ne l'ignore pas. Si vous définissez un délai d'expiration de partition plus long que celui de la table, le délai d'expiration de la table est prioritaire.
  • description : description de la table, entre guillemets.
  • key:value : paire clé/valeur qui représente un libellé. Vous pouvez saisir plusieurs libellés en utilisant une liste de libellés séparés par des virgules.
  • project_id : ID de votre projet.
  • dataset : ensemble de données dans votre projet.
  • table : nom de la table partitionnée que vous créez.

Lorsque vous spécifiez le schéma sur la ligne de commande, vous ne pouvez pas inclure de type RECORD (STRUCT) ni de description de colonne. Vous ne pouvez pas non plus spécifier le mode de la colonne. Tous les modes par défaut sont définis sur NULLABLE. Pour inclure des descriptions, des modes et des types RECORD, fournissez plutôt un fichier de schéma JSON.

Exemples :

Saisissez la commande suivante pour créer une table en cluster nommée myclusteredtable dans mydataset, et non dans votre projet par défaut. La table est une table partitionnée (partitionnée en fonction d'une colonne TIMESTAMP). Le délai d'expiration du partitionnement est défini sur 86 400 secondes (un jour), le délai d'expiration de la table sur 2 592 000 secondes (un mois de 30 jours), la description sur This is my clustered table et le libellé sur organization:development. La commande utilise le raccourci -t au lieu de --table.

Le schéma est spécifié de manière intégrée comme suit : timestamp:timestamp,customer_id:string,transaction_amount:float. Le champ de clustering spécifié customer_id est utilisé pour mettre en cluster les partitions.

bq mk -t \
--expiration 2592000 \
--schema 'timestamp:timestamp,customer_id:string,transaction_amount:float' \
--time_partitioning_field timestamp \
--clustering_fields customer_id \
--time_partitioning_expiration 86400  \
--description "This is my clustered table" \
--label org:dev \
mydataset.myclusteredtable

Saisissez la commande suivante pour créer une table en cluster nommée myclusteredtable dans myotherproject, et non dans votre projet par défaut. La table est une table partitionnée par temps d'ingestion. Le délai d'expiration du partitionnement est défini sur 259 200 secondes (trois jours), la description sur This is my partitioned table et le libellé sur organization:development. La commande utilise le raccourci -t au lieu de --table. Cette commande ne spécifie pas d'expiration de table. Si l'ensemble de données possède une expiration de table par défaut, celle-ci est appliquée. Si l'ensemble de données n'a pas de délai d'expiration de table par défaut, la table n'expire jamais, mais les partitions expirent au bout de trois jours.

Le schéma est spécifié dans un fichier JSON local : /tmp/myschema.json. Le champ customer_id permet de mettre en cluster les partitions.

bq mk -t \
--expiration 2592000 \
--schema /tmp/myschema.json \
--time_partitioning_type=DAY \
--clustering_fields=customer_id \
--time_partitioning_expiration 86400  \
--description "This is my partitioned table" \
--label org:dev \
myotherproject:mydataset.myclusteredtable

Une fois la table créée, vous pouvez mettre à jour le délai d'expiration de table, le délai d'expiration de partition, la description et les libellés de la table partitionnée.

API

Appelez la méthode tables.insert avec une ressource de table définie qui spécifie les propriétés timePartitioning, clustering.fields et schema.

Go

Avant d'essayer l'exemple ci-dessous, suivez la procédure de configuration pour Go décrite dans le guide de démarrage rapide de BigQuery : Utiliser les bibliothèques clientes. Pour en savoir plus, consultez la documentation de référence sur l'API BigQuery Go.

import (
	"context"
	"fmt"
	"time"

	"cloud.google.com/go/bigquery"
)

// createTableClustered demonstrates creating a BigQuery table with advanced properties like
// partitioning and clustering features.
func createTableClustered(projectID, datasetID, tableID string) error {
	// projectID := "my-project-id"
	// datasetID := "mydatasetid"
	// tableID := "mytableid"
	ctx := context.Background()

	client, err := bigquery.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("bigquery.NewClient: %v", err)
	}
	defer client.Close()

	sampleSchema := bigquery.Schema{
		{Name: "timestamp", Type: bigquery.TimestampFieldType},
		{Name: "origin", Type: bigquery.StringFieldType},
		{Name: "destination", Type: bigquery.StringFieldType},
		{Name: "amount", Type: bigquery.NumericFieldType},
	}
	metaData := &bigquery.TableMetadata{
		Schema: sampleSchema,
		TimePartitioning: &bigquery.TimePartitioning{
			Field:      "timestamp",
			Expiration: 90 * 24 * time.Hour,
		},
		Clustering: &bigquery.Clustering{
			Fields: []string{"origin", "destination"},
		},
	}
	tableRef := client.Dataset(datasetID).Table(tableID)
	if err := tableRef.Create(ctx, metaData); err != nil {
		return err
	}
	return nil
}

Java

Avant d'essayer l'exemple ci-dessous, suivez la procédure de configuration pour Java décrite dans le 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 Java.

import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.Clustering;
import com.google.cloud.bigquery.Field;
import com.google.cloud.bigquery.Schema;
import com.google.cloud.bigquery.StandardSQLTypeName;
import com.google.cloud.bigquery.StandardTableDefinition;
import com.google.cloud.bigquery.TableId;
import com.google.cloud.bigquery.TableInfo;
import com.google.cloud.bigquery.TimePartitioning;
import com.google.common.collect.ImmutableList;

public class CreateClusteredTable {
  public static void runCreateClusteredTable() {
    // TODO(developer): Replace these variables before running the sample.
    String datasetName = "MY_DATASET_NAME";
    String tableName = "MY_TABLE_NAME";
    createClusteredTable(datasetName, tableName);
  }

  public static void createClusteredTable(String datasetName, String tableName) {
    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();

      TableId tableId = TableId.of(datasetName, tableName);

      TimePartitioning partitioning = TimePartitioning.of(TimePartitioning.Type.DAY);

      Schema schema =
          Schema.of(
              Field.of("name", StandardSQLTypeName.STRING),
              Field.of("post_abbr", StandardSQLTypeName.STRING),
              Field.of("date", StandardSQLTypeName.DATE));

      Clustering clustering =
          Clustering.newBuilder().setFields(ImmutableList.of("name", "post_abbr")).build();

      StandardTableDefinition tableDefinition =
          StandardTableDefinition.newBuilder()
              .setSchema(schema)
              .setTimePartitioning(partitioning)
              .setClustering(clustering)
              .build();
      TableInfo tableInfo = TableInfo.newBuilder(tableId, tableDefinition).build();

      bigquery.create(tableInfo);
      System.out.println("Clustered table created successfully");
    } catch (BigQueryException e) {
      System.out.println("Clustered table was not created. \n" + e.toString());
    }
  }
}

Créer une table en cluster à partir d'un résultat de requête

Deux options s'offrent à vous pour créer une table en cluster à partir d'un résultat de requête :

Vous pouvez créer une table en cluster en interrogeant une table partitionnée ou une table non partitionnée. Vous ne pouvez pas transformer une table existante en une table en cluster à l'aide de résultats de requête.

Lorsque vous créez une table en cluster à partir d'un résultat de requête, vous devez utiliser le langage SQL standard. Actuellement, l'ancien SQL ne permet pas d'interroger les tables en cluster ou d'écrire les résultats de requêtes dans des tables en cluster.

Console

Vous ne pouvez pas spécifier des options de clustering pour une table de destination lorsque vous interrogez des données à l'aide de l'UI Web BigQuery de la console, sauf si une instruction LDD est utilisée. Pour en savoir plus, consultez la page Utiliser les instructions de langage de définition de données.

UI classique

Il n'est pas possible de spécifier des options de clustering pour une table de destination lors de l'interrogation de données à l'aide de l'interface utilisateur Web de BigQuery, sauf si une instruction LDD est utilisée. Pour en savoir plus, consultez la page Utiliser les instructions de langage de définition de données.

CLI

Entrez la commande suivante pour créer une nouvelle table de destination en cluster à partir d'un résultat de requête :

bq --location=location query \
--use_legacy_sql=false 'query'

Remplacez l'élément suivant :

  • location : nom de votre emplacement. L'option --location est facultative. Par exemple, si vous utilisez BigQuery dans la région de Tokyo, vous pouvez définir la valeur de l'option sur asia-northeast1. Vous pouvez définir une valeur par défaut correspondant à l'emplacement en utilisant le fichier .bigqueryrc.
  • query : requête en syntaxe SQL standard. Il n'est actuellement pas possible d'utiliser l'ancien SQL pour interroger des tables en cluster ou pour écrire des résultats de requête dans des tables en cluster. La requête peut contenir une instruction LDD CREATE TABLE spécifiant les options de création de la table en cluster. L'instruction LDD peut être utilisée à la place des indicateurs de ligne de commande individuels.

Exemples :

Saisissez la commande suivante pour écrire les résultats de la requête dans une table de destination en cluster nommée myclusteredtable au sein de l'ensemble de données mydataset. mydataset se trouve dans votre projet par défaut. La requête extrait les données d'une table non partitionnée : mytable. La colonne customer_id de la table permet de mettre en cluster la table. La colonne timestamp de la table permet de créer une table partitionnée.

bq query --use_legacy_sql=false \
'CREATE TABLE
   mydataset.myclusteredtable
 PARTITION BY
   DATE(timestamp)
 CLUSTER BY
   customer_id AS
 SELECT
   *
 FROM
   `mydataset.mytable`'

API

Pour enregistrer des résultats de requête dans une table en cluster, appelez la méthode jobs.insert, configurez une tâche de requête (query) et incluez une instruction LDD CREATE TABLE qui crée la table en cluster.

Spécifiez votre emplacement dans la propriété location de la section jobReference de la ressource de tâche.

Créer une table en cluster lors du chargement de données

Vous pouvez créer une table en cluster en spécifiant les colonnes de clustering lorsque vous chargez des données dans une nouvelle table. Vous n'avez pas besoin de créer une table vide avant de charger des données. Vous pouvez créer la table en cluster et charger les données en même temps.

Pour en savoir plus sur le chargement des données, consultez la page Introduction au chargement de données dans BigQuery.

Pour définir le clustering lors de la définition d'une tâche de chargement, procédez comme suit :

API

Pour définir la configuration de clustering lors de la création d'une table via une tâche de chargement, vous pouvez insérer les propriétés Clustering pour la table.

Go

Avant d'essayer l'exemple ci-dessous, suivez la procédure de configuration pour Go décrite dans le guide de démarrage rapide de BigQuery : Utiliser les bibliothèques clientes. Pour en savoir plus, consultez la documentation de référence sur l'API BigQuery Go.

import (
	"context"
	"fmt"

	"cloud.google.com/go/bigquery"
)

// importClusteredTable demonstrates creating a table from a load job and defining partitioning and clustering
// properties.
func importClusteredTable(projectID, destDatasetID, destTableID string) error {
	// projectID := "my-project-id"
	// datasetID := "mydataset"
	// tableID := "mytable"
	ctx := context.Background()
	client, err := bigquery.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("bigquery.NewClient: %v", err)
	}
	defer client.Close()

	gcsRef := bigquery.NewGCSReference("gs://cloud-samples-data/bigquery/sample-transactions/transactions.csv")
	gcsRef.SkipLeadingRows = 1
	gcsRef.Schema = bigquery.Schema{
		{Name: "timestamp", Type: bigquery.TimestampFieldType},
		{Name: "origin", Type: bigquery.StringFieldType},
		{Name: "destination", Type: bigquery.StringFieldType},
		{Name: "amount", Type: bigquery.NumericFieldType},
	}
	loader := client.Dataset(destDatasetID).Table(destTableID).LoaderFrom(gcsRef)
	loader.TimePartitioning = &bigquery.TimePartitioning{
		Field: "timestamp",
	}
	loader.Clustering = &bigquery.Clustering{
		Fields: []string{"origin", "destination"},
	}
	loader.WriteDisposition = bigquery.WriteEmpty

	job, err := loader.Run(ctx)
	if err != nil {
		return err
	}
	status, err := job.Wait(ctx)
	if err != nil {
		return err
	}

	if status.Err() != nil {
		return fmt.Errorf("job completed with error: %v", status.Err())
	}
	return nil
}

Java

Avant d'essayer l'exemple ci-dessous, suivez la procédure de configuration pour Java décrite dans le 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 Java.

import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.Clustering;
import com.google.cloud.bigquery.Field;
import com.google.cloud.bigquery.FormatOptions;
import com.google.cloud.bigquery.Job;
import com.google.cloud.bigquery.JobInfo;
import com.google.cloud.bigquery.LoadJobConfiguration;
import com.google.cloud.bigquery.Schema;
import com.google.cloud.bigquery.StandardSQLTypeName;
import com.google.cloud.bigquery.TableId;
import com.google.cloud.bigquery.TimePartitioning;
import com.google.common.collect.ImmutableList;

public class LoadTableClustered {

  public static void runLoadTableClustered() throws Exception {
    // TODO(developer): Replace these variables before running the sample.
    String datasetName = "MY_DATASET_NAME";
    String tableName = "MY_TABLE_NAME";
    String sourceUri = "/path/to/file.csv";
    loadTableClustered(datasetName, tableName, sourceUri);
  }

  public static void loadTableClustered(String datasetName, String tableName, String sourceUri)
      throws Exception {
    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();

      TableId tableId = TableId.of(datasetName, tableName);

      Schema schema =
          Schema.of(
              Field.of("name", StandardSQLTypeName.STRING),
              Field.of("post_abbr", StandardSQLTypeName.STRING),
              Field.of("date", StandardSQLTypeName.DATE));

      TimePartitioning partitioning = TimePartitioning.of(TimePartitioning.Type.DAY);

      Clustering clustering =
          Clustering.newBuilder().setFields(ImmutableList.of("name", "post_abbr")).build();

      LoadJobConfiguration loadJobConfig =
          LoadJobConfiguration.builder(tableId, sourceUri)
              .setFormatOptions(FormatOptions.csv())
              .setSchema(schema)
              .setTimePartitioning(partitioning)
              .setClustering(clustering)
              .build();

      Job loadJob = bigquery.create(JobInfo.newBuilder(loadJobConfig).build());

      // Load data from a GCS parquet file into the table
      // Blocks until this load table job completes its execution, either failing or succeeding.
      Job completedJob = loadJob.waitFor();

      // Check for errors
      if (completedJob == null) {
        throw new Exception("Job not executed since it no longer exists.");
      } else if (completedJob.getStatus().getError() != null) {
        // You can also look at queryJob.getStatus().getExecutionErrors() for all
        // errors, not just the latest one.
        throw new Exception(
            "BigQuery was unable to load into the table due to an error: \n"
                + loadJob.getStatus().getError());
      }
      System.out.println("Data successfully loaded into clustered table during load job");
    } catch (BigQueryException | InterruptedException e) {
      System.out.println("Data not loaded into clustered table during load job \n" + e.toString());
    }
  }
}

Contrôler l'accès aux tables en cluster

Vous ne pouvez pas attribuer de contrôles d'accès directement au niveau des tables ou des vues. Le niveau le plus bas des ressources BigQuery auquel vous pouvez accorder l'accès se situe au niveau de l'ensemble de données. Pour configurer l'accès aux tables et aux vues, vous attribuez un rôle Cloud IAM à une entité située au niveau de l'ensemble de données ou à un niveau supérieur.

L'attribution d'un rôle au niveau de l'ensemble de données spécifie les opérations qu'une entité est autorisée à effectuer sur les tables et les vues de cet ensemble de données spécifique. Pour en savoir plus sur la configuration des contrôles d'accès aux ensembles de données, consultez la page Contrôler l'accès aux ensembles de données.

Vous pouvez également attribuer des rôles Cloud IAM à un niveau supérieur dans la hiérarchie des ressources Google Cloud (par exemple, au niveau du projet, du dossier ou de l'organisation). L'attribution de rôles à un niveau supérieur accorde à l'entité un accès à un ensemble de ressources plus large. Par exemple, si vous attribuez un rôle à une entité au niveau du projet, elle obtient des autorisations qui s'appliquent à tous les ensembles de données du projet. Pour en savoir plus sur l'attribution de droits d'accès aux ressources, consultez la page Accorder, modifier et révoquer les accès à des ressources dans la documentation Cloud IAM.

Vous pouvez également créer des rôles personnalisés Cloud IAM. Si vous créez un rôle personnalisé, les autorisations que vous accordez dépendent des opérations spécifiques que vous souhaitez autoriser l'entité à effectuer.

Pour en savoir plus sur les rôles et les autorisations, consultez les pages suivantes :

Utiliser des tables en cluster

Obtenir des informations sur des tables en cluster

Vous pouvez obtenir des informations sur les tables comme suit :

  • En utilisant Cloud Console ou l'UI Web classique de BigQuery
  • En exécutant la commande bq show de la CLI
  • En appelant la méthode API tables.get
  • En interrogeant des vues INFORMATION_SCHEMA

Autorisations requises

Pour obtenir des informations sur les tables, vous devez au minimum disposer des autorisations bigquery.tables.get. Les rôles Cloud IAM prédéfinis suivants incluent les autorisations bigquery.tables.get :

  • bigquery.metadataViewer
  • bigquery.dataViewer
  • bigquery.dataOwner
  • bigquery.dataEditor
  • bigquery.admin

En outre, si un utilisateur possède les autorisations bigquery.datasets.create, il obtient également un accès bigquery.dataOwner à l'ensemble de données qu'il crée. L'accès bigquery.dataOwner permet à l'utilisateur d'obtenir des informations sur les tables d'un ensemble de données.

Pour en savoir plus sur les rôles et les autorisations Cloud IAM dans BigQuery, consultez la page Rôles et autorisations prédéfinis.

Obtenir des informations sur une table en cluster

Pour afficher des informations sur une table en cluster, procédez comme suit :

Console

  1. Dans Google Cloud Console, accédez au volet Ressources. Cliquez sur le nom de votre ensemble de données pour le développer, puis sur le nom de la table que vous voulez afficher.

  2. Cliquez sur Détails. Cette page affiche les détails de la table, y compris les colonnes de clustering.

    Détails de la table.

UI classique

  1. Dans le volet de navigation, cliquez sur la flèche vers le bas flèche vers le bas située à gauche de l'ensemble de données pour le développer, ou double-cliquez sur son nom. Les tables et vues de ce dernier s'affichent.

  2. Cliquez sur le nom de la table.

  3. Cliquez sur Détails. La page Détails de la table affiche les détails de la table, y compris les colonnes de clustering.

    Détails de la table en cluster.

CLI

Exécutez la commande bq show pour afficher toutes les informations sur la table. L'option --schema permet de n'afficher que les informations de schéma de table. L'option --format peut être utilisée pour contrôler le résultat.

Si vous souhaitez obtenir des informations sur une table se trouvant dans un projet autre que celui par défaut, ajoutez l'ID du projet au nom de l'ensemble de données, en respectant le format suivant : project_id:dataset.

bq show \
--schema \
--format=prettyjson \
project_id:dataset.table

Remplacez l'élément suivant :

  • project_id : ID de votre projet.
  • dataset : nom de l'ensemble de données.
  • table : nom de la table.

Exemples :

Saisissez la commande suivante pour afficher toutes les informations sur la table myclusteredtable de l'ensemble de données mydataset. mydataset se trouve dans votre projet par défaut.

bq show --format=prettyjson mydataset.myclusteredtable

Le résultat doit se présenter sous la forme suivante :

{
  "clustering": {
    "fields": [
      "customer_id"
    ]
  },
...
}

API

Appelez la méthode bigquery.tables.get et définissez tous les paramètres pertinents.

SQL

Pour les tables en cluster, vous pouvez interroger la colonne CLUSTERING_ORDINAL_POSITION dans la vue INFORMATION_SCHEMA.COLUMNS pour récupérer des informations sur les colonnes de clustering d'une table.

-- Set up a table with clustering.
CREATE TABLE myDataset.data (column1 INT64, column2 INT64)
PARTITION BY _PARTITIONDATE
CLUSTER BY column1, column2;

-- This query returns 1 for column1 and 2 for column2.
SELECT column_name, clustering_ordinal_position
FROM myDataset.INFORMATION_SCHEMA.COLUMNS;

D'autres métadonnées de table sont disponibles via les vues TABLES, TABLE_OPTIONS, COLUMNS et COLUMN_FIELD_PATH dans INFORMATION_SCHEMA.

Répertorier les tables en cluster dans un ensemble de données

Vous pouvez répertorier les tables en cluster d'ensembles de données à l'aide des méthodes suivantes :

  • En utilisant Cloud Console ou l'UI Web classique de BigQuery
  • En exécutant la commande bq ls de la CLI
  • En appelant la méthode API tables.list
  • En utilisant les bibliothèques clientes
  • En interrogeant la colonne CLUSTERING_ORDINAL_POSITION dans la vue INFORMATION_SCHEMA.COLUMNS

Les autorisations requises pour répertorier les tables en cluster et les étapes pour y arriver sont les mêmes que pour les tables partitionnées. Pour découvrir comment répertorier des tables, consultez la section Répertorier les tables partitionnées dans un ensemble de données.

Modifier la spécification du clustering

En appelant les méthodes tables.update ou tables.patch, vous pouvez modifier ou supprimer les spécifications de clustering des tables. L'ensemble de colonnes en cluster d'une table en cluster peut également être remplacé par un autre ensemble de colonnes. Cette méthode de mise à jour de l'ensemble de colonnes de clustering est particulièrement utile pour les tables intégrant des insertions en flux continu, car celles-ci ne peuvent pas facilement être échangées dans le cas contraire.

Lorsqu'une table hors cluster est convertie en table en cluster ou que l'ensemble de colonnes en cluster est modifié, la remise en cluster automatique ne fonctionne qu'à partir de ce moment. Par exemple, une table hors cluster de 1 Po qui est convertie en table en cluster à l'aide de tables.update contiendra toujours 1 Po de données hors cluster. La remise en cluster automatique ne s'applique qu'aux nouvelles données validées dans la table après la mise à jour.

Fonctionnalités en cours de développement

Les fonctionnalités suivantes sont en cours de développement, mais ne sont pas encore disponibles dans la version alpha :

  • Prise en charge du clustering pour les tables natives (non partitionnées)
  • Réduction des coûts pour certains types de requêtes qui utilisent des filtres sur des colonnes de clustering

Étapes suivantes