Agregar valores en el momento de la escritura

Si deseas agregar tus datos en Bigtable en el momento de la escritura, puedes usar agregaciones. Son celdas de tablas de Bigtable que agregan valores de celdas a medida que se escriben los datos. Cuando agregas un valor nuevo, una función de agregación combina el valor con el valor agregado que ya está en la celda. Otras bases de datos hacen referencia a una funcionalidad similar como contadores o contadores distribuidos.

El tipo de agregación que ofrece Bigtable es suma. Cuando agregas un valor a una celda agregada, el valor de la celda se reemplaza por la suma del valor recién agregado y el valor actual de la celda.

Durante la versión preliminar, puedes trabajar con agregados mediante la CLI de cbt y las bibliotecas cliente de Bigtable para C++, Go y Java.

En este documento, se proporciona una descripción general de las agregaciones, se muestra cómo crear una familia de columnas de agregación y se proporcionan ejemplos de cómo agregar un valor a una celda de agregación. Antes de leer este documento, debes familiarizarte con la descripción general de Bigtable y las escrituras.

Cuándo usar agregados

Los agregados de Bigtable son útiles en situaciones en las que te interesan los datos de una entidad en conjunto y no como datos individuales. Si migras a Bigtable desde bases de datos como Apache Cassandra o Redis, puedes usar los agregados de Bigtable en lugares en los que antes dependías de los contadores en estos sistemas.

Buckets de tiempo

Puedes usar buckets de tiempo para obtener valores agregados de un período, como una hora, un día o una semana. En lugar de agregar datos antes o después de escribirlos en la tabla, debes agregar valores nuevos para agregar las celdas de la tabla.

Por ejemplo, si ejecutas un servicio que ayuda a las organizaciones benéficas a recaudar dinero, es posible que desees saber la cantidad de donaciones en línea por día para cada campaña, pero no necesitas saber la hora exacta de cada donación ni el importe por hora. En tu tabla, las claves de fila representan los ID de organizaciones sin fines de lucro y creas una familia de columnas agregada llamada donations. Los calificadores de columnas de la fila son ID de campaña.

A medida que se recibe cada cantidad de donaciones recibida en un día determinado para una campaña, se suma a la suma de la celda agregada en la columna de ese día. Cada solicitud de adición para la celda utiliza una marca de tiempo truncada al comienzo del día, de modo que, en efecto, cada solicitud tenga la misma marca de tiempo. Truncar las marcas de tiempo garantiza que todas las donaciones de ese día se agreguen a la misma celda. Al día siguiente, todas tus solicitudes se envían a una celda nueva, con marcas de tiempo truncadas a la nueva fecha, y ese patrón continúa.

Según tu caso de uso, puedes optar por crear columnas nuevas para tus agregaciones nuevas. Si deseas obtener más información sobre los buckets de tiempo, consulta Diseño de esquemas para datos de series temporales.

Optimización de flujos de trabajo

La agregación te permite agregar los datos en tu tabla de Bigtable sin necesidad de usar ningún ETL o software de procesamiento de transmisión para agregar tus datos antes o después de escribirlos en Bigtable. Por ejemplo, si tu aplicación ya publicó mensajes en Pub/Sub y, luego, usó Dataflow para leer los mensajes y agregar datos antes de escribirlos en Bigtable, podrías enviar los datos directamente para agregar celdas en Bigtable.

Familias de columnas de agregación

Para crear y actualizar celdas agregadas, debes tener una o más familias de columnas agregadas en tu tabla; es decir, familias de columnas que solo contengan celdas agregadas. Puedes crearlas cuando creas una tabla o puedes agregar una familia de columnas agregada a una tabla que ya está en uso. Cuando creas la familia de columnas, especificas el tipo de agregación, como suma.

No puedes convertir una familia de columnas que contiene datos no agregados en una familia de columnas agregada. Las columnas en las familias de columnas agregadas no pueden contener celdas que no sean agregadas, y las familias de columnas estándar no pueden contener celdas agregadas.

Para crear una tabla nueva con una familia de columnas agregada, consulta Crea una tabla. Para agregar una familia de columnas agregada a una tabla, consulta Cómo agregar familias de columnas.

Tipos de agregación

Bigtable admite el tipo de agregación sum. El tipo de entrada que se admite para las sumas es Int64.

Marcas de tiempo

Una celda de agregación se define por clave de fila, familia de columnas, calificador de columna y marca de tiempo. Usas la misma marca de tiempo cada vez que agregas datos a la celda. Si envías un valor a la misma clave de fila, familia de columnas y mismo calificador de columna, pero con una marca de tiempo diferente, se crea una nueva celda de agregación en la columna.

Una solicitud para agregar que se envía a una celda agregada debe incluir una marca de tiempo.

Tipo de entrada

El tipo de entrada del valor en la solicitud de agregado debe coincidir con el tipo de entrada con el que se crea la familia de columnas. Por ejemplo, si envías un valor de string a una familia de columnas configurada para Int64, se rechaza la solicitud.

AddToCell

Una solicitud de adición envía una mutación AddToCell en la API de Bigtable Data. Por el contrario, una solicitud de escritura no agregada envía una mutación SetCell. Para obtener más información, consulta la referencia de la API de datos. Las operaciones AddToCell están sujetas a los mismos límites de operaciones que otras mutaciones de tablas.

En una tabla replicada, una celda agregada converge en el mismo valor total en todos los clústeres dentro del retraso de replicación actual. El valor total es la suma de todas las mutaciones de AddToCell que se enviaron a esa celda en todos los clústeres desde la última operación de eliminación o desde que se creó la celda.

Agrega ejemplos de solicitudes

En los siguientes ejemplos, se muestra cómo agregar un valor a una celda agregada. Los ejemplos se suman a una suma en una familia de columnas que espera el tipo de entrada Int64.

cbt

cbt addtocell TABLE_ID ROW_KEY FAMILY_NAME:COLUMN_QUALIFER=VALUE@TIMESTAMP

Reemplaza lo siguiente:

  • TABLE_ID: el identificador permanente de la tabla
  • ROW_KEY: Es la clave de fila.
  • FAMILY_NAME: Es el nombre de la familia de columnas agregada.
  • COLUMN_QUALIFIER: Es un identificador para la columna.
  • VALUE: Es el valor que se agregará a la celda.
  • TIMESTAMP: Es una marca de tiempo de Unix en microsegundos, como 1710868850000000.

Ejemplo:

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

Go

Para obtener información sobre cómo instalar y usar la biblioteca cliente de Bigtable, consulta Bibliotecas cliente de Bigtable.

Para autenticarte en Bigtable, configura las credenciales predeterminadas de la aplicación. Si deseas obtener más información, consulta Configura la autenticación para bibliotecas cliente.

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

Para obtener información sobre cómo instalar y usar la biblioteca cliente de Bigtable, consulta Bibliotecas cliente de Bigtable.

Para autenticarte en Bigtable, 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.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());
    }
  }
}

¿Qué sigue?