Neste tópico, descrevemos como gravar um carimbo de data/hora de confirmação para cada operação de inserção e atualização executada com o Spanner.
Visão geral dos carimbos de data/hora de confirmação
O carimbo de data/hora de confirmação, com base na tecnologia TrueTime, é o horário em que uma transação é confirmada no banco de dados. É possível armazenar atomicamente o carimbo de data/hora de confirmação de uma transação em uma coluna. Usando os carimbos de data/hora de confirmação armazenados em tabelas, determine a ordem exata de mutações e recursos de versão como registros de alterações.
Para inserir carimbos de data/hora de confirmação no seu banco de dados, siga as etapas a seguir:
Crie uma coluna do tipo
SPANNER.COMMIT_TIMESTAMP
. Exemplo:CREATE TABLE Performances ( ... LastUpdateTime SPANNER.COMMIT_TIMESTAMP NOT NULL, ... PRIMARY KEY (...) ) ;
Se você estiver executando inserções ou atualizações com a DML, use a função
SPANNER.PENDING_COMMIT_TIMESTAMP()
para gravar o carimbo de data/hora de confirmação.Se você estiver executando inserções ou atualizações com instruções ou mutações preparadas, use a string de marcador
SPANNER.COMMIT_TIMESTAMP()
para sua coluna de carimbo de data/hora de confirmação. Também é possível usar a constante do carimbo de data/hora de confirmação fornecida pela biblioteca de cliente. Por exemplo, essa constante no cliente Java éValue.COMMIT_TIMESTAMP
.
Quando o Spanner confirma a transação usando esses marcadores como valores de coluna, o carimbo de data/hora de confirmação real é gravado na coluna especificada. Em seguida, use esse valor da coluna para criar um histórico de atualizações da tabela.
Os valores de carimbo de data/hora de commit não têm garantia de exclusividade. As transações gravadas em conjuntos de campos não sobrepostos podem ter o mesmo carimbo de data/hora. As transações gravadas em conjuntos de campos sobrepostos têm carimbos de data/hora exclusivos.
Os carimbos de data/hora de confirmação do Spanner têm granularidade de microssegundos e são convertidos em nanossegundos quando armazenados em colunas SPANNER.COMMIT_TIMESTAMP
.
Chaves e índices
Use uma coluna de carimbo de data/hora de confirmação como uma coluna de chave primária ou como uma coluna sem chave. As chaves primárias podem ser definidas como ASC
ou DESC
.
ASC
(padrão): as chaves crescentes são ideais para responder a consultas de uma hora específica em diante.DESC
: as chaves decrescentes mantêm as linhas mais recentes no topo da tabela. Elas dão acesso rápido aos registros mais recentes.
Evite pontos de acesso
O uso de carimbos de data/hora de confirmação nos cenários a seguir cria pontos de acesso que reduzem o desempenho dos dados:
Coluna de carimbo de data/hora de confirmação como a primeira parte da chave primária de uma tabela.
CREATE TABLE Users ( LastAccess SPANNER.COMMIT_TIMESTAMP NOT NULL, UserId INT64 NOT NULL, ... PRIMARY KEY (LastAccess, UserId) ) ;
Coluna da chave primária do carimbo de data/hora de confirmação como a primeira parte de um índice secundário.
CREATE INDEX UsersByLastAccess ON Users(LastAccess)
ou
CREATE INDEX UsersByLastAccessAndName ON Users(LastAccess, FirstName)
Os pontos de acesso reduzem o desempenho dos dados, mesmo com baixas taxas de gravação. Quando os carimbos de data/hora de confirmação são ativados em colunas que não são chave e nem estão indexadas, não há sobrecarga de desempenho.
Adicionar uma coluna de carimbo de data/hora de confirmação a uma tabela atual
Para adicionar uma coluna de carimbo de data/hora de confirmação a uma tabela existente, use a instrução ALTER TABLE
. Por exemplo, para adicionar uma coluna LastUpdateTime
à tabela Performances
, use a seguinte instrução:
ALTER TABLE Performances ADD COLUMN LastUpdateTime SPANNER.COMMIT_TIMESTAMP
NOT NULL;
Gravar um carimbo de data/hora de confirmação usando uma instrução DML
Use a função SPANNER.PENDING_COMMIT_TIMESTAMP()
para gravar o carimbo
de data/hora de confirmação em uma instrução DML. O Spanner seleciona o carimbo de data/hora de confirmação quando a transação é confirmada.
A instrução DML a seguir atualiza a coluna LastUpdateTime
na
tabela Performances
com o carimbo de data/hora de confirmação:
UPDATE Performances SET LastUpdateTime = SPANNER.PENDING_COMMIT_TIMESTAMP()
WHERE SingerId=1 AND VenueId=2 AND EventDate="2015-10-21"
Inserir uma linha usando uma mutação
Ao inserir uma linha, o Spanner só grava o valor do carimbo de data/hora de confirmação se você incluir a coluna na lista de colunas e transmitir a string de marcador spanner.commit_timestamp()
(ou constante da biblioteca de cliente) como o valor dela. Exemplo:
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Se você tiver mutações em linhas de várias tabelas, precisará especificar spanner.commit_timestamp()
(ou a constante da biblioteca de cliente) para a coluna de carimbo de data/hora de confirmação em cada tabela.
Atualizar uma linha usando uma mutação
Ao atualizar uma linha, o Spanner só grava o valor do carimbo de data/hora de confirmação se você incluir a coluna na lista de colunas e transmitir a string de marcador spanner.commit_timestamp()
(ou constante da biblioteca de cliente) como o valor dela. Não atualize a chave primária de uma linha. Para atualizar a chave primária, exclua a linha atual e crie uma nova.
Por exemplo, para atualizar uma coluna de carimbo de data/hora de confirmação chamada LastUpdateTime
:
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Se você tiver mutações nas linhas de várias tabelas, precisará especificar spanner.commit_timestamp()
(ou a constante da biblioteca de cliente) para a coluna de carimbo de data/hora de confirmação em cada tabela.
Consultar uma coluna de carimbo de data/hora de confirmação
O exemplo a seguir consulta a coluna do carimbo de data/hora de commit da tabela.
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Forneça seu próprio valor para a coluna do carimbo de data/hora de confirmação
No código, é possível fornecer seu próprio valor para a coluna do carimbo de data/hora de confirmação, em vez de transmitir spanner.commit_timestamp()
(ou a constante de biblioteca de cliente disponível) como o valor da coluna. O valor precisa ser um carimbo de data/hora no passado. Essa restrição garante que gravar carimbos de data/hora seja uma operação rápida e barata. Uma maneira fácil de confirmar se um valor está no passado é comparar ele com o valor retornado pela função SQL CURRENT_TIMESTAMP
.
O servidor retornará um erro FailedPrecondition
se um carimbo de data/hora futuro for especificado.
Criar um log de mudanças
Suponhamos que você queira criar um registro de alterações de cada mutação feita em uma tabela e use esse registro na auditoria. Um exemplo seria uma tabela que armazenasse o histórico de alterações em documentos de processamento de texto. O carimbo de data/hora de commit facilita a criação do registro de alterações, porque os carimbos de data/hora podem impor a ordem das entradas do registro de alterações. Crie um registro de alterações que armazene o histórico de alterações em um determinado documento usando um esquema como o exemplo a seguir:
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 criar um registro de alterações, insira uma nova linha em DocumentHistory
na mesma transação em que você inserir ou atualizar uma linha em Document
. Na inserção da nova linha em DocumentHistory
, use o marcador spanner.commit_timestamp()
(ou a constante da biblioteca de cliente) para dizer ao Spanner para gravar o carimbo de data/hora de confirmação na coluna Ts
. A intercalação da tabela DocumentsHistory
com a tabela Documents
permitirá conhecer a localização dos dados, além de inserções e atualizações mais eficientes. No entanto, ela também adiciona a restrição de que as linhas pai e filho precisam ser excluídas juntas. Para manter as linhas em DocumentHistory
depois que as linhas em Documents
forem excluídas, não intercale as tabelas.
Otimizar consultas de dados recentes com carimbos de data/hora de confirmação
Os carimbos de data/hora de confirmação permitem uma otimização do Spanner que pode reduzir a E/S da consulta ao recuperar dados gravados após um determinado momento.
Para ativar essa otimização, a cláusula WHERE
de uma consulta precisa incluir uma comparação entre a coluna de carimbo de data/hora de confirmação da tabela e um horário específico fornecido, com os seguintes atributos:
Forneça o horário específico como uma expressão constante: um literal, um parâmetro ou uma função com argumentos próprios que sejam avaliados como constantes.
Compare se o carimbo de data/hora de confirmação é mais recente do que o determinado usando os operadores
>
ou>=
.Opcionalmente, adicione mais restrições à cláusula
WHERE
comAND
. Estender a cláusula comOR
desqualifica a consulta dessa otimização.
Por exemplo, considere a tabela Performances
a seguir, que inclui uma coluna de carimbo de data/hora de confirmação:
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)
);
Essa consulta se beneficia da otimização do carimbo de data/hora de confirmação descrita anteriormente, porque ela tem uma comparação de maior ou igual a entre a coluna de carimbo de data/hora de confirmação da tabela e uma expressão constante. Neste caso, um literal:
SELECT * FROM Performances WHERE LastUpdateTime >= '2022-01-01';