Confronta DML e mutazioni

Il linguaggio di manipolazione dei dati (DML) e le mutazioni sono due API in Spanner che puoi utilizzare per modificare i dati. Ognuno offre funzionalità di manipolazione dei dati simili. Questa pagina confronta entrambi gli approcci.

Che cos'è il Data Manipulation Language (DML)?

Il linguaggio di manipolazione dei dati (DML) in Spanner ti 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 console di Google Cloud e gcloud spanner.

Spanner offre le due seguenti implementazioni dell'esecuzione DML, ciascuna con proprietà diverse.

  • DML standard: adatto per i carichi di lavoro Online Transaction Processing (OLTP) standard.

    Per ulteriori informazioni, inclusi esempi di codice, consulta Utilizzare DML

  • DML partizionato: progettato per aggiornamenti ed eliminazioni collettivi, come negli esempi riportati di seguito.

    • Pulizia e garbage collection periodici. Alcuni esempi sono l'eliminazione di righe vecchie o l'impostazione di colonne su NULL.

    • Eseguire il backfill delle nuove colonne con i valori predefiniti. Un esempio è l'utilizzo di un'istruzione UPDATE per impostare il valore di una nuova colonna su False se è NULL.

    Per ulteriori informazioni, inclusi esempi di codice, consulta Utilizzare la DML partizionata.

    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 la sezione Modificare i dati utilizzando le scritture 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 contenenti 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 Inserire, aggiornare ed eliminare i 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 dei database.

Operazioni DML Mutazioni
Inserisci dati Supportato Supportato
Elimina dati Supportato Supportato
Aggiorna 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

Le istruzioni DML e le mutazioni differiscono nel supporto delle seguenti funzionalità:

  • Leggi le tue scritture: lettura dei risultati non confermati 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 all'esecuzione dell'commit della transazione. Questo perché le mutazioni in una transazione vengono messe in coda lato client (localmente) e inviate al server nell'ambito 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 immagazzina le mutazioni nel client fino al commit e controlla le limitazioni al momento del commit. La valutazione delle limitazioni dopo ogni istruzione DML consente a Spanner di garantire che i dati restituiti da una query successiva nella stessa transazione siano coerenti con lo schema.

  • Sintassi SQL: la 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 gli enunciati DML o le mutazioni in una singola transazione, ma non entrambi.

Il seguente esempio Java illustra un comportamento potenzialmente sorprendente. Il codice inserisce due righe in Album utilizzando l'API Mutation. Lo snippet chiama quindi executeUpdate() per aggiornare le righe appena inserite e chiama 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 all'esecuzione commit della transazione. Idealmente, dovremmo avere scrittura con buffer solo alla fine della transazione.

Passaggi successivi