DML (Data Manipulation Language) e mutazioni sono due API di Spanner che puoi utilizzare per modificare i dati. Entrambe offrono funzionalità di manipolazione dei dati simili. Questa pagina confronta entrambi gli approcci.
Che cos'è DML (Data Manipulation Language)?
DML (Data Manipulation Language) in Spanner consente di manipolare i dati nelle tabelle del database utilizzando le istruzioni INSERT, UPDATE e DELETE. Puoi eseguire istruzioni DML utilizzando le
librerie client, la
Google Cloud console e gcloud spanner.
Spanner offre le seguenti due implementazioni dell'esecuzione DML, ognuna con proprietà diverse.
DML standard : adatta ai carichi di lavoro standard di Online Transaction Processing (OLTP).
Per ulteriori informazioni, inclusi esempi di codice, consulta Utilizzo di DML
DML partizionato : progettato per aggiornamenti ed eliminazioni collettivi, come negli esempi seguenti.
Pulizia periodica e garbage collection. Ad esempio, eliminare le righe precedenti o impostare le colonne su NULL.
Riempimento delle nuove colonne con valori predefiniti. Ad esempio, utilizzare un'istruzione UPDATE per impostare il valore di una nuova colonna su False quando è NULL.
Per ulteriori informazioni, inclusi esempi di codice, consulta Utilizzo di DML partizionato.
Puoi utilizzare le scritture in batch per un numero elevato di operazioni di scrittura senza operazioni di lettura che non richiedono transazioni atomiche. Per ulteriori informazioni, consulta Modificare i dati utilizzando le scritture in batch.
Che cosa sono le mutazioni?
Una mutazione rappresenta una sequenza di inserimenti, aggiornamenti ed eliminazioni che Spanner applica in modo atomico a righe e tabelle diverse in un database. Puoi includere operazioni che si applicano a righe o tabelle diverse in una mutazione. Dopo aver definito una o più mutazioni che contengono una o più scritture, devi applicare la mutazione per eseguire il commit delle scritture. Ogni modifica viene applicata nell'ordine in cui è stata aggiunta alla mutazione.
Per ulteriori informazioni, inclusi esempi di codice, consulta Inserimento, aggiornamento ed eliminazione dei dati utilizzando le mutazioni.
Confronto delle funzionalità tra DML e mutazioni
La tabella seguente riassume il supporto di DML e mutazioni per le operazioni e le funzionalità comuni del database.
| Operazioni | DML | Mutazioni |
|---|---|---|
| Inserisci i dati | Supportato | Supportato |
| Elimina dati | Supportato | Supportato |
| Aggiorna i dati | Supportato | Supportato |
| Inserisci o ignora i dati | Supportato | Non supportato |
| Leggi le tue scritture (RYW) | Supportato | Non supportato |
| Inserisci o aggiorna i dati (upsert) | Supportato | Supportato |
| Sintassi SQL | Supportato | Non supportato |
| Controllo dei vincoli | Dopo ogni istruzione | Al momento del commit |
| Applicazione del limite di mutazioni (inclusi gli indici) | Per istruzione (viene reimpostato dopo l'esecuzione) | Per commit (cumulativo) |
DML e mutazioni differiscono nel supporto delle seguenti funzionalità:
Leggi le tue scritture: lettura dei risultati non sottoposti a commit all'interno di una transazione attiva. Le modifiche apportate utilizzando le istruzioni DML sono visibili alle istruzioni successive nella stessa transazione. Questo è diverso dall'utilizzo delle mutazioni, in cui le modifiche non sono visibili in nessuna lettura (incluse le letture eseguite nella stessa transazione) fino al commit della transazione. Questo perché le mutazioni in una transazione vengono memorizzate nel buffer lato client (localmente) e inviate al server come parte dell'operazione di commit. Di conseguenza, le mutazioni nella richiesta di commit non sono visibili alle istruzioni SQL o DML all'interno della stessa transazione.
Controllo dei vincoli: Spanner controlla i vincoli dopo ogni istruzione DML. Questo è diverso dall'utilizzo delle mutazioni, in cui Spanner memorizza le mutazioni nel buffer del client fino al commit e controlla i vincoli al momento del commit. La valutazione dei vincoli dopo ogni istruzione DML consente a Spanner di garantire che i dati restituiti da una query successiva nella stessa transazione restituiscano dati coerenti con lo schema.
Applicazione del limite di mutazioni: per DML, il limite di mutazioni di 80.000 (inclusi gli indici) viene applicato per istruzione e viene reimpostato dopo l'esecuzione dell'istruzione. Ciò consente a una singola transazione di eseguire più istruzioni DML che superano collettivamente 80.000 mutazioni, a condizione che nessuna singola istruzione superi il limite. Per l'API Mutation, che può essere utilizzata solo come parte dell'operazione di commit, il limite di 80.000 mutazioni (inclusi gli indici) è cumulativo per tutte le mutazioni nel commit. Entrambi i metodi sono soggetti al limite di dimensioni delle transazioni di 100 MiB.
Sintassi SQL: DML fornisce un modo convenzionale per manipolare i dati. Puoi riutilizzare le competenze SQL per modificare i dati utilizzando l'API DML.
Best practice: evita di combinare DML e mutazioni nella stessa transazione
Se una transazione contiene sia istruzioni DML sia mutazioni nella richiesta di commit, Spanner esegue le istruzioni DML prima delle mutazioni. Per evitare di dover tenere conto dell'ordine di esecuzione nel codice della libreria client, devi utilizzare le istruzioni DML o le mutazioni in una singola transazione, ma non entrambe.
L'esempio Java seguente illustra un comportamento potenzialmente sorprendente. Il codice inserisce due righe in Albums utilizzando l'API Mutation. Lo snippet chiama quindi executeUpdate() per aggiornare le righe appena inserite e executeQuery() per leggere gli album aggiornati.
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 esegui questo codice, vedrai 0 record aggiornati. Perché? Questo accade perché le modifiche apportate utilizzando le mutazioni non sono visibili alle istruzioni successive fino al commit della transazione. Idealmente, avremmo dovuto memorizzare nel buffer le scritture solo alla fine della transazione.
Passaggi successivi
Scopri come modificare i dati utilizzando DML.
Scopri come modificare i dati utilizzando le mutazioni.
Per trovare il conteggio delle mutazioni per una transazione, consulta Recupero delle statistiche di commit per una transazione.
Scopri le best practice di DML (Data Manipulation Language).