En esta página, se describe cómo escribir una marca de tiempo de confirmación en cada operación de inserción y actualización que realizas con Spanner en bases de datos con dialecto de PostgreSQL.
Inserta marcas de tiempo de confirmación
Una marca de tiempo de confirmación, basada en la tecnología TrueTime, es el momento en que se confirma una transacción en la base de datos. Puedes almacenar de forma atómica la marca de tiempo de confirmación de una transacción en una columna. Con las marcas de tiempo de confirmación almacenadas en las tablas, puedes determinar el orden exacto de las mutaciones y compilar funciones como los registros de cambios.
Para insertar marcas de tiempo de confirmación en tu base de datos, completa los siguientes pasos:
Crea una columna de tipo
SPANNER.COMMIT_TIMESTAMP. Por ejemplo:CREATE TABLE Performances ( ... LastUpdateTime SPANNER.COMMIT_TIMESTAMP NOT NULL, ... PRIMARY KEY (...) ) ;Si realizas inserciones o actualizaciones con DML, usa la función
SPANNER.PENDING_COMMIT_TIMESTAMP()para escribir la marca de tiempo de confirmación.Si realizas inserciones o actualizaciones con instrucciones preparadas o mutaciones, usa la cadena de marcador de posición
SPANNER.COMMIT_TIMESTAMP()para tu columna de marcas de tiempo de confirmación. También puedes usar la constante de marca de tiempo de confirmación que proporciona la biblioteca cliente. Por ejemplo, esta constante en el cliente de Java esValue.COMMIT_TIMESTAMP.
Cuando Spanner confirma la transacción mediante estos marcadores de posición como valores de columna, la marca de tiempo de confirmación real se escribe en la columna especificada. Luego, puedes usar este valor de columna para crear un historial de actualizaciones de la tabla.
No se garantiza que los valores de marca de tiempo de confirmación sean únicos. Las transacciones que escriben en conjuntos de campos que no se superponen podrían tener la misma marca de tiempo. Las transacciones que escriben en conjuntos de campos que se superponen tienen marcas de tiempo únicas.
Las marcas de tiempo de confirmación de Spanner tienen un nivel de detalle de microsegundos y se convierten a nanosegundos cuando se almacenan en columnas SPANNER.COMMIT_TIMESTAMP.
Claves e índices
Puedes usar una columna de marcas de tiempo de confirmación como una columna de clave principal o como una columna sin clave. Las claves principales se pueden definir como ASC o DESC.
ASC(predeterminado): Las claves ascendentes son ideales para responder consultas de un tiempo específico.DESC: Las claves descendentes mantienen las filas más recientes en la parte superior de la tabla. Proporcionan acceso rápido a los registros más recientes.
Evita los hotspots
El uso de marcas de tiempo de confirmación en las siguientes situaciones crea hotspots que reducen el rendimiento de los datos:
En una columna de marca de tiempo de confirmación que funciona como la primera parte de la clave primaria de una tabla
CREATE TABLE Users ( LastAccess SPANNER.COMMIT_TIMESTAMP NOT NULL, UserId bigint NOT NULL, ... PRIMARY KEY (LastAccess, UserId) ) ;En una columna de clave primaria de marca de tiempo de confirmación que funciona como la primera parte de un índice secundario
CREATE INDEX UsersByLastAccess ON Users(LastAccess)o
CREATE INDEX UsersByLastAccessAndName ON Users(LastAccess, FirstName)
Los hotspots reducen el rendimiento de los datos, incluso con tasas de escritura bajas. No se produce una sobrecarga de rendimiento si las marcas de tiempo de confirmación se habilitan en columnas sin clave que no estén indexadas.
Agrega una columna de marcas de tiempo de confirmación a una tabla existente
Para agregar una columna de marcas de tiempo de confirmación a una tabla existente, usa la declaración ALTER TABLE. Por ejemplo, para agregar una columna LastUpdateTime a la tabla Performances, usa la siguiente declaración:
ALTER TABLE Performances ADD COLUMN LastUpdateTime SPANNER.COMMIT_TIMESTAMP;
Escribe una marca de tiempo de confirmación mediante una declaración DML
Usa la función SPANNER.PENDING_COMMIT_TIMESTAMP() para escribir la marca de tiempo de confirmación en una declaración DML. Spanner selecciona la marca de tiempo de confirmación cuando se confirma la transacción.
La siguiente declaración DML actualiza la columna LastUpdateTime en la tabla Performances con la marca de tiempo de confirmación:
UPDATE Performances SET LastUpdateTime = SPANNER.PENDING_COMMIT_TIMESTAMP()
WHERE SingerId=1 AND VenueId=2 AND EventDate="2015-10-21"
Inserta una fila con una mutación
Cuando insertas una fila, Spanner escribe el valor de la marca de tiempo de confirmación solo si incluyes la columna en la lista de columnas y pasas la cadena de marcador de posición spanner.commit_timestamp() (o la constante de la biblioteca cliente) como su valor. Por ejemplo:
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Si tienes mutaciones en filas de varias tablas, debes especificar spanner.commit_timestamp() (o la constante de la biblioteca cliente) en la columna de marcas de tiempo de confirmación de cada tabla.
Actualiza una fila con una mutación
Cuando actualizas una fila, Spanner escribe el valor de la marca de tiempo de confirmación solo si incluyes la columna en la lista de columnas y pasas la cadena de marcador de posición spanner.commit_timestamp() (o la constante de la biblioteca cliente) como su valor. No puedes actualizar la clave primaria de una fila. Para actualizar la clave primaria, borra la fila existente y crea una nueva.
Por ejemplo, para actualizar una columna de marcas de tiempo de confirmación llamada LastUpdateTime, realiza lo siguiente:
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Si tienes mutaciones en filas de varias tablas, debes especificar spanner.commit_timestamp() (o la constante de la biblioteca cliente) en la columna de marcas de tiempo de confirmación de cada tabla.
Consulta una columna de marcas de tiempo de confirmación
En el siguiente ejemplo, se consulta la columna de marcas de tiempo de confirmación de la tabla.
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Proporciona tu propio valor para la columna de marcas de tiempo de confirmación
En tu código, puedes proporcionar tu propio valor para la columna de marcas de tiempo de confirmación en lugar de pasar spanner.commit_timestamp() (o la constante de la biblioteca cliente disponible) como el valor de la columna. El valor debe ser una marca de tiempo anterior. Esta restricción garantiza que escribir marcas de tiempo sea una operación rápida y económica. Una forma de confirmar que un valor es anterior es compararlo con el valor que muestra la función de SQL CURRENT_TIMESTAMP. El servidor muestra un error FailedPrecondition si se especifica una marca de tiempo futura.
Crea un registro de cambios
Supongamos que deseas crear un registro de cambios de todas las mutaciones que se producen en una tabla y, luego, usarlo para realizar auditorías. Un ejemplo sería una tabla que almacena el historial de cambios de los documentos de procesamiento de texto. Las marcas de tiempo de confirmación facilitan la creación del registro de cambios, ya que pueden aplicar de forma forzosa el orden de las entradas del registro de cambios. Puedes crear un registro de cambios que almacene el historial de cambios de un documento determinado mediante un esquema como se muestra en el siguiente ejemplo:
CREATE TABLE Documents (
UserId int8 NOT NULL,
DocumentId int8 NOT NULL,
Contents text NOT NULL,
PRIMARY KEY (UserId, DocumentId)
);
CREATE TABLE DocumentHistory (
UserId int8 NOT NULL,
DocumentId int8 NOT NULL,
Ts SPANNER.COMMIT_TIMESTAMP NOT NULL,
Delta text,
PRIMARY KEY (UserId, DocumentId, Ts)
) INTERLEAVE IN PARENT Documents;
Para crear un registro de cambios, inserta una fila nueva en el DocumentHistory en la misma
transacción en la que insertas o actualizas una fila en el Document. En la inserción de la fila nueva en DocumentHistory, usa el marcador de posición spanner.commit_timestamp() (o la constante de la biblioteca cliente) para indicar a Spanner que escriba la marca de tiempo de confirmación en la columna Ts.
La intercalación de la tabla DocumentsHistory con la tabla Documents permite la localidad de los datos y la realización de inserciones y actualizaciones más eficientes. Sin embargo, también agregará la restricción de que las filas principales y secundarias se deben borrar juntas. Para conservar las filas en DocumentHistory después de que se borren las filas en Documents, no intercales las tablas.
Optimiza las consultas de datos recientes con marcas de tiempo de confirmación
Las marcas de tiempo de confirmación optimizan tu base de datos de Spanner y pueden reducir la E/S de las consultas cuando recuperas datos escritos después de un momento determinado.
Para activar esta optimización, la cláusula WHERE de una consulta debe incluir una comparación entre la columna de marcas de tiempo de confirmación de una tabla y un momento específico que proporciones, con los siguientes atributos:
Proporciona el momento específico como una expresión constante: un literal, un parámetro o una función cuyos argumentos se evalúan como constantes.
Compara si la marca de tiempo de confirmación es más reciente que el momento determinado, a través de los operadores
>o>=.De manera opcional, agrega más restricciones a la cláusula
WHEREconAND. Extender la cláusula conORdescalifica la consulta de esta optimización.
Por ejemplo, considera la siguiente tabla Performances, que incluye una columna de marcas de tiempo de confirmación:
CREATE TABLE Performances (
SingerId bigint NOT NULL,
VenueId bigint NOT NULL,
EventDate timestamp with time zone NOT NULL,
Revenue bigint,
LastUpdateTime spanner.commit_timestamp,
PRIMARY KEY(SingerId, VenueId, EventDate)
);
Esta consulta se beneficia de la optimización de marca de tiempo de confirmación que se describió antes, ya que tiene una comparación mayor o igual que entre la columna de marcas de tiempo de confirmación de la tabla y una expresión constante, en este caso, un literal:
SELECT * FROM Performances WHERE LastUpdateTime >= '2022-01-01';