Nesta página, descrevemos as práticas recomendadas para o uso da linguagem de manipulação de dados (DML, na sigla em inglês) e da DML particionada.
Use uma cláusula WHERE para reduzir o escopo dos bloqueios
As instruções DML são executadas dentro de transações de leitura e gravação. Quando o Spanner lê dados,
adquire bloqueios de leitura compartilhados em partes limitadas dos intervalos de linhas que você lê. Especificamente, ele adquire esses bloqueios apenas nas colunas acessadas. Os bloqueios podem incluir dados que não
atendam à condição de filtro da cláusula WHERE
.
Quando o Spanner modifica dados usando instruções DML, ele adquire bloqueios exclusivos no dados específicos que você está modificando. Além disso, ele adquire bloqueios compartilhados da mesma maneira que quando você lê dados. Caso sua solicitação inclua grandes intervalos de linhas ou uma tabela inteira, os arquivos bloqueios podem impedir que outras transações avancem em paralelo.
Para modificar os dados da forma mais eficiente possível, use uma cláusula WHERE
que permita
Spanner para ler apenas as linhas necessárias. É possível atingir essa meta com um filtro na chave principal ou na chave de um índice secundário. A cláusula WHERE
limita o escopo
os bloqueios compartilhados e permite que o Spanner processe a atualização com mais eficiência.
Por exemplo, suponha que um dos músicos da tabela Singers
altere seu nome e você precise atualizar essa informação no banco de dados. É possível executar a seguinte instrução DML
mas força o Spanner a verificar a tabela inteira e adquire os bloqueios compartilhados que
que cobrem toda a tabela. como resultado, o Spanner precisa ler mais dados do que o necessário.
transações simultâneas não podem modificar os dados em paralelo:
-- ANTI-PATTERN: SENDING AN UPDATE WITHOUT THE PRIMARY KEY COLUMN
-- IN THE WHERE CLAUSE
UPDATE Singers SET FirstName = "Marcel"
WHERE FirstName = "Marc" AND LastName = "Richards";
Para tornar a atualização mais eficiente, inclua a coluna SingerId
na cláusula WHERE
. A coluna SingerId
é a única coluna de chave primária da tabela Singers
:
-- ANTI-PATTERN: SENDING AN UPDATE THAT MUST SCAN THE ENTIRE TABLE
UPDATE Singers SET FirstName = "Marcel"
WHERE FirstName = "Marc" AND LastName = "Richards"
Se não houver índice em FirstName
ou LastName
, você precisará
verificar a tabela inteira para encontrar os cantores-alvo. Se você não quiser adicionar
para tornar a atualização mais eficiente, inclua a coluna SingerId
na cláusula WHERE
.
A coluna SingerId
é a única coluna de chave primária para
Singers
. Para encontrá-lo, execute SELECT
em uma instância separada.
transação somente leitura antes da transação de atualização:
SELECT SingerId
FROM Singers
WHERE FirstName = "Marc" AND LastName = "Richards"
-- Recommended: Including a seekable filter in the where clause
UPDATE Singers SET FirstName = "Marcel"
WHERE SingerId = 1;
Evite usar instruções DML e mutações na mesma transação
O Spanner armazena em buffer inserções, atualizações e exclusões realizadas usando a DML do lado do servidor, e os resultados são visíveis para as instâncias SQL e instruções DML na mesma transação. Esse comportamento é diferente das API Mutation, em que o Spanner armazena as mutações no lado do cliente e as envia para o lado do servidor como parte a operação de confirmação. Como resultado, as mutações na solicitação de confirmação não são visíveis para as instruções SQL ou DML na mesma transação.
Evite usar instruções DML e mutações na mesma transação. Se você usar os dois na mesma transação, você precisa considerar a ordem do no código da biblioteca de cliente. Se uma transação contém DML e mutações na mesma solicitação, o Spanner executa a instruções DML antes das mutações.
Para operações que são compatíveis apenas com o uso de mutações, convém
combinar instruções DML e mutações na mesma transação, por exemplo,
insert_or_update
Se você usar ambos, o buffer só gravará no final da transação.
Use a função PENDING_COMMIT_TIMESTAMP para gravar carimbos de data/hora de confirmação
GoogleSQL
Use a função 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
commits.
PostgreSQL
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
commits.
DML particionada e funções date e timestamp
A DML particionada usa uma ou mais transações que podem ser executadas e confirmadas em momentos diferentes. Se você usar as funções date ou timestamp, as linhas modificadas poderão conter valores diferentes.
Melhorar a latência com DML em lote
Para reduzir a latência, use a DML em lote para enviar várias instruções DML para o Spanner em uma única rodada cliente-servidor viagem.
O DML em lote pode aplicar otimizações a grupos de instruções em um lote para permitir atualizações de dados mais rápidas e eficientes.
Executar gravações com uma única solicitação
O Spanner otimiza automaticamente grupos contíguos de funções INSERT, instruções em lote UPDATE ou DELETE que tenham valores de parâmetro diferentes; caso não violem as dependências de dados.
Por exemplo, considere um cenário em que você quer inserir um grande conjunto de novas linhas em uma tabela chamada
Albums
. Para permitir que o Spanner otimize todos instruçõesINSERT
necessárias em uma ação única e eficiente do lado do servidor, comece escrevendo uma instrução DML apropriada que use uma consulta SQL parâmetros:INSERT INTO Albums (SingerId, AlbumId, AlbumTitle) VALUES (@Singer, @Album, @Title);
Em seguida, envie ao Spanner um lote DML que invoque essa instrução de forma repetida e contígua, com as repetições diferindo apenas no valores que você vincula aos três parâmetros de consulta da instrução. O Spanner otimiza essas instruções DML estruturalmente idênticas em uma única operação do lado do servidor antes de executá-las.
Executar gravações em paralelo
O Spanner otimiza automaticamente grupos contíguos de instruções DML executando em paralelo quando isso não viola as dependências de dados. Essa otimização traz benefícios de desempenho para um conjunto mais amplo de instruções DML em lote, porque pode ser aplicada a uma combinação de tipos de instruções DML (INSERT, UPDATE e DELETE) e a instruções DML parametrizadas ou não parametrizadas.
Por exemplo, nosso esquema de exemplo tem as tabelas
Singers
,Albums
eAccounts
.Albums
é intercalado entreSingers
e armazena informações sobre os álbuns deSingers
. O seguinte grupo contíguo de instruções grava novas linhas em várias tabelas e não tem dados complexos dependências.INSERT INTO Singers (SingerId, Name) VALUES(1, "John Doe"); INSERT INTO Singers (SingerId, Name) VALUES(2, "Marcel Richards"); INSERT INTO Albums(SingerId, AlbumId, AlbumTitle) VALUES (1, 10001, "Album 1"); INSERT INTO Albums(SingerId, AlbumId, AlbumTitle) VALUES (1, 10002, "Album 2"); INSERT INTO Albums(SingerId, AlbumId, AlbumTitle) VALUES (2, 10001, "Album 1"); UPDATE Accounts SET Balance = 100 WHERE AccountId = @AccountId;
O Spanner otimiza esse grupo de instruções DML executando em paralelo. As gravações são aplicadas na ordem das instruções no lote e mantêm a semântica da DML em lote se uma instrução falhar durante a execução.