En esta página se describe cómo escribir una marca de tiempo de confirmación para cada operación de inserción y actualización que realices con Spanner en bases de datos con dialecto PostgreSQL.
Insertar marcas de tiempo de confirmación
La marca de tiempo de confirmación, basada en la tecnología TrueTime, es el momento en el 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 las confirmaciones almacenadas en las tablas, puedes determinar el orden exacto de las mutaciones y crear funciones como los registros de cambios.
Para insertar marcas de tiempo de confirmación en tu base de datos, sigue estos pasos:
Crea una columna de tipo
SPANNER.COMMIT_TIMESTAMP
. Por ejemplo:CREATE TABLE Performances ( ... LastUpdateTime SPANNER.COMMIT_TIMESTAMP NOT NULL, ... PRIMARY KEY (...) ) ;
Si insertas o actualizas datos con DML, usa la función
SPANNER.PENDING_COMMIT_TIMESTAMP()
para escribir la marca de tiempo de confirmación.Si insertas o actualizas datos con instrucciones preparadas o mutaciones, usa la cadena de marcador de posición
SPANNER.COMMIT_TIMESTAMP()
para la columna de marca de tiempo de confirmación. También puedes usar la constante de marca de tiempo de confirmación proporcionada por la biblioteca de cliente. Por ejemplo, esta constante del cliente de Java esValue.COMMIT_TIMESTAMP
.
Cuando Spanner confirma la transacción usando estos marcadores de posición como valores de columna, la marca de tiempo de confirmación real se escribe en la columna especificada. Después, puede usar este valor de columna para crear un historial de actualizaciones de la tabla.
No se garantiza que los valores de la marca de tiempo de la confirmación sean únicos. Las transacciones que escriben en conjuntos de campos que no se solapan pueden tener la misma marca de tiempo. Las transacciones que escriben en conjuntos de campos superpuestos tienen marcas de tiempo únicas.
Las marcas de tiempo de confirmación de Spanner tienen una granularidad de microsegundos y se convierten a nanosegundos cuando se almacenan en columnas SPANNER.COMMIT_TIMESTAMP
.
Claves e índices
Puede usar una columna de marca de tiempo de confirmación como columna de clave principal o como columna que no sea clave. Las claves principales se pueden definir como ASC
o DESC
.
ASC
(predeterminado): las claves ascendentes son ideales para responder a consultas desde un momento específico en adelante.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.
Evitar puntos de acceso
Si se usan marcas de tiempo de confirmación en los siguientes casos, se crean puntos de acceso, lo que reduce el rendimiento de los datos:
Columna de marca de tiempo de confirmación como primera parte de la clave principal de una tabla.
CREATE TABLE Users ( LastAccess SPANNER.COMMIT_TIMESTAMP NOT NULL, UserId bigint NOT NULL, ... PRIMARY KEY (LastAccess, UserId) ) ;
Columna de clave principal de la marca de tiempo de confirmación como primera parte de un índice secundario.
CREATE INDEX UsersByLastAccess ON Users(LastAccess)
o
CREATE INDEX UsersByLastAccessAndName ON Users(LastAccess, FirstName)
Los puntos de acceso reducen el rendimiento de los datos, incluso con tasas de escritura bajas. No hay sobrecarga de rendimiento si las marcas de tiempo de confirmación están habilitadas en columnas que no son de clave y que no están indexadas.
Añadir una columna de marca de tiempo de confirmación a una tabla
Para añadir una columna de marca de tiempo de confirmación a una tabla, usa la instrucción ALTER TABLE
. Por ejemplo, para añadir una columna LastUpdateTime
a la tabla Performances
, usa la siguiente instrucción:
ALTER TABLE Performances ADD COLUMN LastUpdateTime SPANNER.COMMIT_TIMESTAMP;
Escribir una marca de tiempo de confirmación con una instrucción DML
Usa la función SPANNER.PENDING_COMMIT_TIMESTAMP()
para escribir la marca de tiempo de confirmación en una instrucción DML. Spanner selecciona la marca de tiempo de confirmación cuando se confirma la transacción.
La siguiente instrucción DML actualiza la columna LastUpdateTime
de 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"
Insertar una fila con una mutación
Al insertar una fila, Spanner escribe el valor de la marca de tiempo de confirmación solo si incluye la columna en la lista de columnas y le asigna la cadena de marcador de posición spanner.commit_timestamp()
(o la constante de la biblioteca de cliente). 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 una constante de la biblioteca de cliente) en la columna de marca de tiempo de confirmación de cada tabla.
Actualizar una fila mediante una mutación
Al actualizar una fila, Spanner escribe el valor de la marca de tiempo de confirmación solo si incluye la columna en la lista de columnas y pasa la cadena de marcador de posición spanner.commit_timestamp()
(o la constante de la biblioteca de cliente) como valor. No puedes actualizar la clave principal de una fila. Para actualizar la clave principal, elimina la fila y crea una nueva.
Por ejemplo, para actualizar una columna de marca de tiempo de confirmación llamada LastUpdateTime
, haz 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 marca de tiempo de confirmación de cada tabla.
Consultar una columna de marca de tiempo de confirmación
En el siguiente ejemplo se consulta la columna de marca de tiempo de confirmación de la tabla.
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Proporcionar su propio valor para la columna de marca de tiempo de confirmación
En su código, puede proporcionar su propio valor para la columna de marca de tiempo de confirmación
en lugar de enviar spanner.commit_timestamp()
(o la constante de la biblioteca de cliente disponible) como valor de la columna. El valor debe ser una marca de tiempo anterior a la fecha actual. Esta restricción asegura 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 devuelto por la función SQL CURRENT_TIMESTAMP
. El servidor devuelve un error FailedPrecondition
si se especifica una marca de tiempo futura.
Crear un registro de cambios
Supongamos que quieres crear un registro de cambios de cada mutación que se produzca en una tabla y, a continuación, usar ese registro de cambios para realizar auditorías. Por ejemplo, una tabla que almacene el historial de cambios de los documentos de procesamiento de textos. La marca de tiempo de la confirmación facilita la creación del registro de cambios, ya que las marcas de tiempo pueden imponer 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 con un esquema como el del 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, inserte una fila en DocumentHistory
en la misma transacción en la que inserte o actualice una fila en Document
. En la inserción de la nueva fila en DocumentHistory
, use 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 la confirmación en la columna Ts
.
Entrelazar la tabla DocumentsHistory
con la tabla Documents
permite
la localidad de los datos y que las inserciones y las actualizaciones sean más eficientes. Sin embargo, también añade la restricción de que las filas principales y secundarias deben eliminarse juntas. Para conservar las filas de DocumentHistory
después de eliminar las filas de Documents
, no entrelaces las tablas.
Optimizar 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/de las consultas al recuperar datos escritos después de una hora concreta.
Para activar esta optimización, la cláusula WHERE
de una consulta debe incluir una comparación entre la columna de marca de tiempo de confirmación de una tabla y una hora específica que proporciones, con los siguientes atributos:
Indica la hora específica como una expresión constante: un literal, un parámetro o una función cuyos argumentos se evalúen como constantes.
Compara si la marca de tiempo de la confirmación es más reciente que la hora indicada mediante los operadores
>
o>=
.También puede añadir más restricciones a la cláusula
WHERE
conAND
. Si se amplía la cláusula conOR
, la consulta no podrá beneficiarse de esta optimización.
Por ejemplo, considere la siguiente tabla Performances
, que incluye una columna de marca 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 la marca de tiempo de confirmación descrita anteriormente, ya que incluye una comparación mayor o igual que entre la columna de marca 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';