A linguagem de manipulação de dados (DML) e as mutações são duas APIs no Spanner que podem ser usadas para modificar dados. Cada uma oferece recursos semelhantes de manipulação de dados. Esta página compara as duas abordagens.
O que é a linguagem de manipulação de dados (DML)?
A linguagem de manipulação de dados (DML, na sigla em inglês) no Spanner permite
manipular dados nas tabelas do banco de dados usando as instruções INSERT, UPDATE e DELETE. É possível executar instruções DML usando as
bibliotecas de cliente, o
console doGoogle Cloud e o gcloud spanner.
O Spanner oferece as duas implementações de execução de DML a seguir, cada uma com propriedades diferentes.
DML padrão: adequado para cargas de trabalho padrão de processamento de transações on-line (OLTP, na sigla em inglês).
Para mais informações, incluindo exemplos de código, consulte Como usar a DML.
DML particionada: projetada para atualizações e exclusões em massa, como nos exemplos a seguir.
Limpeza periódica e coleta de lixo. Alguns exemplos são excluir linhas antigas ou definir colunas como NULL.
Preenchimento de novas colunas com valores padrão. Um exemplo é usar uma instrução UPDATE para definir o valor de uma nova coluna como False quando ele for NULL.
Para mais informações, incluindo exemplos de código, consulte Como usar a DML particionada.
É possível usar gravações em lote para um grande número de operações de gravação sem operações de leitura que não exigem transações atômicas. Para mais informações, consulte Modificar dados usando gravações em lote.
O que são mutações?
Uma mutação representa uma sequência de inserções, atualizações e exclusões que o Spanner aplica atomicamente a diferentes linhas e tabelas em um banco de dados. É possível incluir operações que se aplicam a linhas ou tabelas diferentes em uma mutação. Depois de definir uma ou mais mutações que contêm uma ou mais gravações, é necessário aplicar a mutação para confirmar as gravações. Cada alteração é aplicada na ordem em que foram adicionadas à mutação.
Para mais informações, incluindo exemplos de código, consulte Como inserir, atualizar e excluir dados usando mutações.
Comparação de recursos entre DML e mutações
A tabela a seguir resume o suporte à DML e à mutação da operação e dos recursos comuns do banco de dados.
| Operações | DML | Mutações |
|---|---|---|
| Inserir dados | Compatível | Compatível |
| Excluir dados | Compatível | Compatível |
| Atualizar dados | Compatível | Com suporte |
| Inserir ou ignorar dados | Com suporte | Sem suporte |
| Leia suas gravações (RYM, na sigla em inglês) | Compatível | Sem suporte |
| Inserir ou atualizar dados (Upsert) | Com suporte | Com suporte |
| Sintaxe SQL | Com suporte | Não compatível |
| Verificação de restrição | Após cada instrução | No momento do commit |
| Aplicação do limite de mutação (incluindo índices) | Por instrução (redefine após a execução) | Por commit (cumulativo) |
A DML e as mutações divergem no suporte aos seguintes recursos:
Leitura das gravações: leitura de resultados que não passaram por commit em uma transação ativa. As mudanças feitas usando instruções DML ficam visíveis para as instruções subsequentes na mesma transação. Isso é diferente de usar mutações, em que as alterações não são visíveis em nenhuma leitura (incluindo leituras feitas na mesma transação) até a confirmação da transação. Isso ocorre porque as mutações em uma transação são armazenadas no lado do cliente (localmente) e enviadas ao servidor como parte da operação de confirmação. Como resultado, as mutações na solicitação de commit não são visíveis para instruções SQL ou instruções DML na mesma transação.
Verificação de restrições: o Spanner verifica as restrições após cada instrução DML. Isso é diferente de usar mutações, em que o Spanner armazena em buffer as mutações no cliente até o commit e verifica as restrições no momento do commit. Avaliar as restrições após cada instrução DML permite que o Spanner garanta que os dados retornados por uma consulta subsequente na mesma transação sejam consistentes com o esquema.
Aplicação do limite de mutação: para DML, o limite de mutação de 80.000 (incluindo índices) é aplicado por instrução e redefinido após a execução da instrução. Isso permite que uma única transação execute várias instruções DML que, juntas, excedem 80.000 mutações, desde que nenhuma instrução individual ultrapasse o limite. Para a API Mutation, que só pode ser usada como parte da operação de commit, o limite de 80.000 mutações (incluindo índices) é cumulativo em todas as mutações no commit. Os dois métodos estão sujeitos ao limite de tamanho de transação de 100 MiB.
Sintaxe SQL: a DML oferece uma maneira convencional de manipular dados. É possível reutilizar as habilidades do SQL para alterar os dados com a API DML.
Prática recomendada: evite misturar DML e mutação na mesma transação
Se uma transação contiver instruções DML e mutações na solicitação de commit, o Spanner executará as instruções DML antes das mutações. Para não precisar incluir a ordem de execução no código da biblioteca de cliente, use instruções DML ou as mutações em uma única transação, mas não ambas.
O exemplo de Java a seguir ilustra um comportamento potencialmente surpreendente. O código
insere duas linhas nos álbuns usando a API de mutação. O snippet, em seguida, chama
executeUpdate() para atualizar as linhas recém-inseridas e chama executeQuery()
para ler os álbuns atualizados.
static void updateMarketingBudget(DatabaseClient dbClient) {
dbClient
.readWriteTransaction()
.run(
new TransactionCallable<Void>() {
@Override
public Void run(TransactionContext transaction) throws Exception {
transaction.buffer(
Mutation.newInsertBuilder("Albums")
.set("SingerId")
.to(1)
.set("AlbumId")
.to(1)
.set("AlbumTitle")
.to("Total Junk")
.set("MarketingBudget")
.to(800)
.build());
transaction.buffer(
Mutation.newInsertBuilder("Albums")
.set("SingerId")
.to(1)
.set("AlbumId")
.to(2)
.set("AlbumTitle")
.to("Go Go Go")
.set("MarketingBudget")
.to(200)
.build());
// This UPDATE will not include the Albums inserted above.
String sql =
"UPDATE Albums SET MarketingBudget = MarketingBudget * 2"
+ " WHERE SingerId = 1";
long rowCount = transaction.executeUpdate(Statement.of(sql));
System.out.printf("%d records updated.\n", rowCount);
// Read a newly updated record.
sql =
"SELECT SingerId, AlbumId, AlbumTitle FROM Albums"
+ " WHERE SingerId = 1 AND MarketingBudget < 1000";
ResultSet resultSet =
transaction.executeQuery(Statement.of(sql));
while (resultSet.next()) {
System.out.printf(
"%s %s\n",
resultSet.getString("FirstName"),
resultSet.getString("LastName"));
}
return null;
}
});
}
Se você executar esse código, verá 0 registros atualizados. Por quê? Isso acontece porque as alterações feitas com "Mutações" não ficam visíveis para as instruções subsequentes até que a transação seja confirmada. O ideal é ter gravações armazenadas em buffer somente no final da transação.
A seguir
Saiba como modificar dados usando a DML.
Saiba como modificar dados usando mutações.
Para encontrar a contagem de mutações para uma transação, consulte Como recuperar estatísticas de confirmação para uma transação.
Saiba mais sobre as práticas recomendadas da linguagem de manipulação de dados (DML, na sigla em inglês).