Esta página descreve como escrever uma data/hora de confirmação para cada operação de inserção e atualização que realizar com o Spanner em bases de dados com dialeto PostgreSQL.
Inserir indicações de tempo de commits
A data/hora de confirmação, com base na tecnologia TrueTime, é a data/hora em que uma transação é confirmada na base de dados. Pode armazenar atomicamente a data/hora de confirmação de uma transação numa coluna. Usando as datas/horas de confirmação armazenadas em tabelas, pode determinar a ordem exata das mutações e criar funcionalidades como registos de alterações.
Para inserir datas/horas de confirmação na sua base de dados, conclua os seguintes passos:
Crie uma coluna do tipo
SPANNER.COMMIT_TIMESTAMP
. Por exemplo:CREATE TABLE Performances ( ... LastUpdateTime SPANNER.COMMIT_TIMESTAMP NOT NULL, ... PRIMARY KEY (...) ) ;
Se estiver a fazer inserções ou atualizações com DML, use a função
SPANNER.PENDING_COMMIT_TIMESTAMP()
para escrever a data/hora de confirmação.Se estiver a fazer inserções ou atualizações com declarações preparadas ou mutações, use a string de marcador de posição
SPANNER.COMMIT_TIMESTAMP()
para a coluna de data/hora de confirmação. Também pode usar a constante de data/hora de confirmação fornecida pela biblioteca de cliente. Por exemplo, esta constante no cliente Java éValue.COMMIT_TIMESTAMP
.
Quando o Spanner confirma a transação através destes marcadores de posição como valores de colunas, a data/hora de confirmação real é escrita na coluna especificada. Em seguida, pode usar este valor da coluna para criar um histórico de atualizações da tabela.
Não é garantido que os valores de data/hora de confirmação sejam exclusivos. As transações que escrevem em conjuntos de campos não sobrepostos podem ter a mesma data/hora. As transações que escrevem em conjuntos de campos sobrepostos têm informações de data/hora únicas.
As indicações de tempo de confirmação do Spanner têm um nível de detalhe de microssegundos e são convertidas em nanosegundos quando armazenadas em colunas SPANNER.COMMIT_TIMESTAMP
.
Chaves e índices
Pode usar uma coluna de data/hora de confirmação como uma coluna de chave principal ou como uma coluna sem chave. As chaves primárias podem ser definidas como ASC
ou DESC
.
ASC
(predefinição) – As chaves ascendentes são ideais para responder a consultas a partir de um momento específico.DESC
– As chaves descendentes mantêm as linhas mais recentes na parte superior da tabela. Oferecem acesso rápido aos registos mais recentes.
Evite pontos ativos
A utilização de datas/horas de confirmação nos seguintes cenários cria hotspots, o que reduz o desempenho dos dados:
Coluna de data/hora de confirmação como a primeira parte da chave principal de uma tabela.
CREATE TABLE Users ( LastAccess SPANNER.COMMIT_TIMESTAMP NOT NULL, UserId bigint NOT NULL, ... PRIMARY KEY (LastAccess, UserId) ) ;
Coluna de chave principal da 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 críticos reduzem o desempenho dos dados, mesmo com taxas de gravação baixas. Não existe sobrecarga de desempenho se as datas/horas de confirmação estiverem ativadas em colunas não principais que não estejam indexadas.
Adicione uma coluna de data/hora de confirmação a uma tabela existente
Para adicionar uma coluna de data/hora de confirmação a uma tabela existente, use a declaração ALTER TABLE
. Por exemplo, para adicionar uma coluna LastUpdateTime
à tabela Performances
, use a seguinte declaração:
ALTER TABLE Performances ADD COLUMN LastUpdateTime SPANNER.COMMIT_TIMESTAMP;
Escrever uma data/hora de confirmação com uma declaração DML
Use a função SPANNER.PENDING_COMMIT_TIMESTAMP()
para escrever a data/hora de confirmação numa declaração DML. O Spanner seleciona a data/hora de confirmação quando a transação é confirmada.
A seguinte declaração DML atualiza a coluna LastUpdateTime
na tabela Performances
com a data/hora de confirmação:
UPDATE Performances SET LastUpdateTime = SPANNER.PENDING_COMMIT_TIMESTAMP()
WHERE SingerId=1 AND VenueId=2 AND EventDate="2015-10-21"
Insira uma linha através de uma mutação
Quando insere uma linha, o Spanner escreve o valor da data/hora de confirmação apenas se incluir a coluna na lista de colunas e transmitir a string de marcador de posição spanner.commit_timestamp()
(ou a constante da biblioteca de cliente) como respetivo valor. Por exemplo:
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Se tiver mutações em linhas em várias tabelas, tem de especificar spanner.commit_timestamp()
(ou a constante da biblioteca de cliente) para a coluna de data/hora de confirmação em cada tabela.
Atualize uma linha através de uma mutação
Quando atualiza uma linha, o Spanner escreve o valor da data/hora de confirmação apenas se incluir a coluna na lista de colunas e transmitir a string de marcador de posição spanner.commit_timestamp()
(ou a constante da biblioteca de cliente) como respetivo valor. Não pode atualizar a chave principal de uma linha. Para atualizar a chave principal, elimine a linha existente e crie uma nova linha.
Por exemplo, para atualizar uma coluna de data/hora de confirmação denominada LastUpdateTime
:
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Se tiver mutações em linhas em várias tabelas, tem de especificar spanner.commit_timestamp()
(ou a constante da biblioteca de cliente) para a coluna de data/hora de confirmação em cada tabela.
Consultar uma coluna de data/hora de confirmação
O exemplo seguinte consulta a coluna de data/hora de confirmação da tabela.
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Indique o seu próprio valor para a coluna de data/hora de confirmação
No seu código, pode fornecer o seu próprio valor para a coluna de data/hora de confirmação
em vez de transmitir spanner.commit_timestamp()
(ou a constante da biblioteca de cliente disponível) como o valor da coluna. O valor tem de ser uma data/hora no passado. Esta restrição garante que a gravação de indicações de tempo é uma operação barata e rápida. Uma forma de confirmar que um valor está no passado é compará-lo com o valor devolvido pela função SQL CURRENT_TIMESTAMP
. O servidor devolve um erro FailedPrecondition
se for especificada uma data/hora futura.
Crie um registo de alterações
Suponhamos que quer criar um registo de alterações de todas as mutações que ocorrem numa tabela e, em seguida, usar esse registo de alterações para auditoria. Um exemplo seria uma tabela que armazena o histórico de alterações a documentos de processamento de texto. A data/hora de confirmação facilita a criação do histórico de alterações, porque as datas/horas podem aplicar a ordenação das entradas do histórico de alterações. Pode criar um registo de alterações que armazene o histórico de alterações a um determinado documento através de um esquema como o do exemplo seguinte:
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 registo de alterações, insira uma nova linha em DocumentHistory
na mesma transação em que insere ou atualiza uma linha em Document
. Na inserção
da nova linha em DocumentHistory
, use o marcador de posição
spanner.commit_timestamp()
(ou a constante da biblioteca de cliente) para indicar
ao Spanner que escreva a data/hora de confirmação na coluna Ts
.
A intercalação da tabela DocumentsHistory
com a tabela Documents
permite a localidade dos dados e inserções e atualizações mais eficientes. No entanto, também adiciona a restrição de que as linhas principal e secundária têm de ser eliminadas em conjunto. Para manter as linhas em DocumentHistory
depois de as linhas em Documents
serem eliminadas, não
intercale as tabelas.
Otimize as consultas de dados recentes com indicações de tempo de confirmação
As datas/horas de confirmação otimizam a base de dados do Spanner e podem reduzir a E/S de consultas quando recuperam dados escritos após uma determinada hora.
Para ativar esta otimização, a cláusula WHERE
de uma consulta tem de incluir uma comparação entre a coluna de data/hora de confirmação de uma tabela e uma hora específica que indicar, com os seguintes atributos:
Indique a hora específica como uma expressão constante: um literal, um parâmetro ou uma função cujos próprios argumentos são avaliados como constantes.
Compare se a data/hora de confirmação é mais recente do que a hora indicada através dos operadores
>
ou>=
.Opcionalmente, adicione mais restrições à cláusula
WHERE
comAND
. A extensão da cláusula comOR
desqualifica a consulta desta otimização.
Por exemplo, considere a seguinte tabela Performances
, que inclui uma coluna 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)
);
Esta consulta beneficia da otimização da data/hora de confirmação descrita anteriormente, porque tem uma comparação maior ou igual entre a coluna de data/hora de confirmação da tabela e uma expressão constante. Neste caso, trata-se de um literal:
SELECT * FROM Performances WHERE LastUpdateTime >= '2022-01-01';