Valeurs agrégées au moment de l'écriture

Si vous souhaitez agréger vos données dans Bigtable au moment de l'écriture, vous pouvez utiliser des agrégations. Les agrégations sont des cellules de table Bigtable qui agrègent les valeurs des cellules à mesure que les données sont écrites. Lorsque vous ajoutez une valeur, une fonction d'agrégation fusionne la valeur avec la valeur agrégée déjà présente dans la cellule. D'autres bases de données font référence à des fonctionnalités semblables aux compteurs ou aux compteurs distribués.

Bigtable propose le type d'agrégation sum. Lorsque vous ajoutez une valeur à une cellule cumulée pour la somme, la valeur de la cellule est remplacée par la somme de la nouvelle valeur ajoutée et de la valeur actuelle de la cellule.

Pendant la phase de preview, vous pouvez utiliser des agrégats à l'aide de la CLI cbt et des bibliothèques clientes Bigtable pour C++, Go et Java.

Ce document présente les agrégations, montre comment créer une famille de colonnes agrégées et fournit des exemples montrant comment ajouter une valeur à une cellule d'agrégation. Avant de lire ce document, vous devez avoir lu la présentation de Bigtable et les écritures.

Quand utiliser les agrégations

Les agrégations Bigtable sont utiles dans les cas où vous vous souciez des données d'une entité sous forme agrégée et non sous forme de points de données individuels. Si vous migrez vers Bigtable à partir de bases de données telles qu'Apache Cassandra ou Redis, vous pouvez utiliser les agrégations Bigtable aux endroits où vous comptiez auparavant sur des compteurs dans ces systèmes.

Buckets de temps

Vous pouvez utiliser des buckets de temps pour obtenir des valeurs agrégées pour une période donnée, telle qu'une heure, un jour ou une semaine. Au lieu d'agréger des données avant ou après leur écriture dans la table, vous ajoutez de nouvelles valeurs pour agréger les cellules de la table.

Par exemple, si vous gérez un service qui aide des organisations caritatives à collecter des fonds, vous souhaiterez peut-être connaître le nombre de dons en ligne par jour pour chaque campagne, mais vous n'aurez pas besoin de connaître l'heure exacte de chaque don ni le montant horaire. Dans votre table, les clés de ligne représentent les ID d'organisation caritative. Vous créez ainsi une famille de colonnes agrégées appelée donations. Les qualificatifs de colonne sur cette ligne correspondent aux ID de campagne.

Chaque montant de don reçu pour un jour donné pour une campagne est reçu, il est ajouté à la somme figurant dans la cellule globale de la colonne correspondant à ce jour. Chaque requête d'ajout de cellule utilise un horodatage tronqué au début de la journée, de sorte que chaque requête ait le même horodatage. La troncation des codes temporels permet de s'assurer que tous les dons du jour sont ajoutés dans la même cellule. Le lendemain, toutes vos requêtes sont transmises dans une nouvelle cellule en utilisant des horodatages tronqués jusqu'à la nouvelle date, et ce schéma se poursuit.

Selon votre cas d'utilisation, vous pouvez choisir de créer plutôt des colonnes pour vos nouvelles agrégats. En fonction du nombre de buckets que vous prévoyez d'accumuler, vous pouvez envisager une conception de clé de ligne différente.

Pour en savoir plus sur les buckets de temps, consultez la section Concevoir un schéma pour les données de séries temporelles.

Simplification des workflows

Les agrégations vous permettent d'agréger vos données dans votre table Bigtable sans avoir à utiliser de logiciel ETL ou de traitement par flux pour agréger vos données avant ou après leur écriture dans Bigtable. Par exemple, si votre application a déjà publié des messages sur Pub/Sub, puis utilisé Dataflow pour lire les messages et agréger les données avant de les écrire dans Bigtable, vous pouvez envoyer les données directement pour agréger les cellules dans Bigtable.

Agréger des familles de colonnes

Pour créer et mettre à jour des cellules agrégées, vous devez avoir une ou plusieurs familles de colonnes agrégées dans votre table, c'est-à-dire des familles de colonnes ne contenant que des cellules agrégées. Vous pouvez les créer en même temps que la table, ou ajouter une famille de colonnes agrégées à une table déjà utilisée. Lorsque vous créez la famille de colonnes, vous spécifiez le type d'agrégation (par exemple, somme).

Vous ne pouvez pas convertir une famille de colonnes contenant des données non agrégées en famille de colonnes agrégées. Les colonnes des familles de colonnes agrégées ne peuvent pas contenir de cellules non agrégées, et les familles de colonnes standards ne peuvent pas contenir de cellules agrégées.

Pour créer une table avec une famille de colonnes agrégées, consultez la section Créer une table. Pour ajouter une famille de colonnes agrégées à une table, consultez Ajouter des familles de colonnes.

Types d'agrégation

Bigtable accepte le type d'agrégation sum. Le type d'entrée accepté pour les sommes est Int64.

Horodatages

Une cellule agrégée est définie par une clé de ligne, une famille de colonnes, un qualificatif de colonne et un horodatage. Vous utilisez le même horodatage chaque fois que vous ajoutez des données à la cellule. Si vous envoyez une valeur à la même clé de ligne, à la même famille de colonnes et au même qualificatif de colonne, mais avec un horodatage différent, une cellule agrégée est créée dans la colonne.

Une requête d'ajout envoyée à une cellule agrégée doit inclure un code temporel.

Type d'entrée

Le type d'entrée de la valeur dans la requête d'ajout doit correspondre au type d'entrée avec lequel la famille de colonnes est créée. Par exemple, si vous envoyez une valeur de chaîne à une famille de colonnes configurée pour Int64, la requête est rejetée.

AddToCell

Une requête d'ajout envoie une mutation AddToCell dans l'API Bigtable Data. En revanche, une requête d'écriture non agrégée envoie une mutation SetCell. Pour en savoir plus, consultez la documentation de référence de l'API Data. Les opérations AddToCell sont soumises aux mêmes limites d'opérations que les autres mutations de table.

Dans une table répliquée, une cellule agrégée converge vers la même valeur totale dans tous les clusters au cours du délai de réplication actuel. La valeur totale correspond à l'ensemble des AddToCell mutations envoyées à cette cellule dans tous les clusters depuis la dernière opération de suppression ou depuis la création de la cellule.

Ajouter des exemples de requêtes

Les exemples suivants vous montrent comment ajouter une valeur à une cellule agrégée. Les exemples s'ajoutent à une somme dans une famille de colonnes qui attend le type d'entrée Int64.

cbt

cbt addtocell TABLE_ID ROW_KEY FAMILY_NAME:COLUMN_QUALIFER=VALUE@TIMESTAMP

Remplacez les éléments suivants :

  • TABLE_ID : identifiant permanent de la table.
  • ROW_KEY: clé de ligne
  • FAMILY_NAME: nom de la famille de colonnes agrégées
  • COLUMN_QUALIFIER: identifiant de la colonne.
  • VALUE: valeur à ajouter à la cellule
  • TIMESTAMP: code temporel Unix en microsecondes, par exemple 1710868850000000

Exemple :

cbt addtocell mobile-data device-1 updates:week12=100@1710868850000000

Go

Pour savoir comment installer et utiliser la bibliothèque cliente pour Bigtable, consultez la page Bibliothèques clientes Bigtable.

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

import (
	"context"
	"fmt"
	"io"
	"time"

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

func writeAggregate(w io.Writer, projectID, instanceID string, tableName string) error {
	// projectID := "my-project-id"
	// instanceID := "my-instance-id"
	// tableName := "mobile-time-series"

	ctx := context.Background()
	client, err := bigtable.NewClient(ctx, projectID, instanceID)
	if err != nil {
		return fmt.Errorf("bigtable.NewClient: %w", err)
	}
	defer client.Close()
	tbl := client.Open(tableName)
	columnFamilyName := "view_count"
	viewTimestamp, err := time.Parse(time.RFC3339, "2024-03-13T12:41:34Z")
	if err != nil {
		return err
	}
	hourlyBucket := viewTimestamp.Truncate(time.Hour)

	mut := bigtable.NewMutation()
	mut.AddIntToCell(columnFamilyName, "views", bigtable.Time(hourlyBucket), 1)

	rowKey := "page#index.html"
	if err := tbl.Apply(ctx, rowKey, mut); err != nil {
		return fmt.Errorf("Apply: %w", err)
	}

	fmt.Fprintf(w, "Successfully wrote row: %s\n", rowKey)
	return nil
}

Java

Pour savoir comment installer et utiliser la bibliothèque cliente pour Bigtable, consultez la page Bibliothèques clientes Bigtable.

Pour vous authentifier auprès de Bigtable, configurez les 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.bigtable.data.v2.BigtableDataClient;
import com.google.cloud.bigtable.data.v2.models.RowMutation;
import java.time.Instant;
import java.time.temporal.ChronoUnit;

public class WriteAggregate {
  private static final String COUNT_COLUMN_FAMILY_NAME = "view_count";
  private static final long MICROS_PER_MILLI = 1000;

  public static void writeAggregate(String projectId, String instanceId, String tableId) {
    // String projectId = "my-project-id";
    // String instanceId = "my-instance-id";
    // String tableId = "page-view-counter";

    try (BigtableDataClient dataClient = BigtableDataClient.create(projectId, instanceId)) {

      String rowKey = "page#index.html";
      Instant viewTimestamp = Instant.parse("2024-03-13T12:41:34.123Z");

      // Bucket the views for an hour into a single count, giving us an hourly view count for a
      // given page.
      Instant hourlyBucket = viewTimestamp.truncatedTo(ChronoUnit.HOURS);
      long hourlyBucketMicros = hourlyBucket.toEpochMilli() * MICROS_PER_MILLI;

      RowMutation rowMutation =
          RowMutation.create(tableId, rowKey)
              .addToCell(COUNT_COLUMN_FAMILY_NAME, "views", hourlyBucketMicros, 1);

      dataClient.mutateRow(rowMutation);
      System.out.printf("Successfully wrote row %s", rowKey);

    } catch (Exception e) {
      System.out.println("Error during WriteAggregate: \n" + e.toString());
    }
  }
}

Étapes suivantes