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éger 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 désignent des fonctionnalités similaires comme des compteurs ou des compteurs distribués.

Vous pouvez utiliser des agrégations à 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 un 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 connaître 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 intéressez données globales d'une entité 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 des agrégations Bigtable à des endroits où vous vous appuyiez auparavant sur des compteurs dans ces systèmes.

Buckets de temps

Vous pouvez utiliser des buckets temporels pour obtenir des valeurs agrégées sur une période donnée, par exemple une heure, un jour ou une semaine. Au lieu d'agréger les données avant ou après leur écriture dans votre 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 pouvez vous souhaitez connaître le nombre de dons en ligne par jour pour chaque campagne, n'ont pas besoin de connaître l'heure exacte de chaque don ou le montant par heure. Dans dans votre tableau, les clés de ligne représentent les ID des organisations caritatives, et vous créez une colonne d'agrégation famille appelée donations. Les qualificatifs de colonne de la ligne sont les ID de campagne.

Chaque montant de don reçu pour un jour donné pour une campagne est ajouté à la somme de la cellule globale de la colonne pour ce jour. Chaque requête d'ajout pour la cellule utilise un code temporel tronqué au début de la journée, de sorte que chaque requête ait le même code temporel. Le troncage des codes temporels garantit que tous les dons de ce jour sont ajoutés à la même cellule. Le jour suivant, toutes vos requêtes sont placées dans une nouvelle cellule, à l'aide d'horodatages qui sont tronqués jusqu'à la nouvelle date, et ce schéma se poursuit.

Selon votre cas d'utilisation, vous pouvez choisir de créer des colonnes pour vos nouvelles à la place des agrégats. Selon le nombre de buckets que vous prévoyez vous pouvez envisager une conception de clé de ligne différente.

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

Simplifier les workflows

Les agrégations vous permettent de regrouper vos données dans une table Bigtable sans avoir à utiliser de logiciel d'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 dans Pub/Sub, puis utilisé Dataflow pour lire les messages et agréger les données avant de les écrire dans Bigtable, vous pouvez plutôt envoyer les données directement pour agréger des cellules dans Bigtable.

Agréger des familles de colonnes

Pour créer et mettre à jour des cellules agrégées, vous devez disposer d'une ou de plusieurs cellules agrégées familles de colonnes de votre tableau : familles de colonnes ne contenant que des cellules. Vous pouvez les créer en même temps que le tableau, ou ajouter un agrégat à une table qui est 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 Créer une table. Pour ajouter une famille de colonnes agrégatives à une table, consultez Ajouter des familles de colonnes.

Types d'agrégation

Bigtable accepte les types d'agrégation suivants:

Somme

Lorsque vous ajoutez une valeur à une cellule de somme agrégative (sum), la valeur de la cellule est remplacée par la somme de la valeur nouvellement ajoutée et de la valeur actuelle de la cellule. La type d'entrée compatible avec les sommes est Int64.

Minimum

Lorsque vous ajoutez une valeur à une cellule cumulée minimale (min), la valeur de la cellule est remplacée par la valeur la plus faible entre la nouvelle valeur ajoutée et la valeur actuelle la valeur de la cellule. Le type d'entrée pris en charge pour la valeur minimale est Int64.

Maximum

Lorsque vous ajoutez une valeur à une cellule agrégation maximale (max), la valeur de la cellule est remplacée par la valeur la plus élevée entre la valeur nouvellement ajoutée et la valeur actuelle de la cellule. Le type d'entrée accepté pour la valeur maximale est Int64.

HyperLogLog (HLL)

Lorsque vous ajoutez une valeur à une cellule agrégée HLL (inthll), elle est ajoutée à un ensemble probabiliste de toutes les valeurs ajoutées depuis la réinitialisation la plus récente (création de la cellule ou suppression de ses données). La valeur de la cellule représente l'état de cet ensemble. Pour en savoir plus sur l'algorithme HLL, consultez la page HyperLogLog.

Vous pouvez lire les valeurs HLL à l'aide de la bibliothèque Zetasketch. Pour en savoir plus, consultez le dépôt GitHub de Zetasketch. La Le type d'entrée compatible avec HLL est BYTES.

Horodatages

Une cellule agrégative est définie par la clé de ligne, la famille de colonnes, le qualificatif de colonne et l'horodatage. Vous utilisez le même code temporel 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 code temporel différent, une nouvelle cellule agrégative 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 familiale de colonnes configurée pour Int64, la requête est refusé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égative converge vers la même valeur finale dans tous les clusters dans le délai de réplication actuel. La valeur finale est agrégat 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.

Récupération de mémoire

Lors de la récupération de mémoire, les cellules agrégées sont traitées comme n'importe quelle autre cellule: si une est marquée pour suppression, la suppression est répliquée sur tous les clusters du Compute Engine. Pour en savoir plus, consultez la section Réplication et mémoire collection. Si une demande d'ajout est envoyée à une cellule agrégable qui a été supprimée par la récupération de mémoire, une nouvelle une cellule agrégée est créée.

Ajouter des exemples de requêtes

Les exemples suivants vous montrent comment ajouter une valeur à une cellule agrégée. Les exemples 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 section 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 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());
    }
  }
}

Étape suivante