Confronta DML e mutazioni

Data Manipulation Language (DML) e Mutazioni sono due API di Spanner che puoi utilizzare per modificare i dati. Ognuno di essi offre funzionalità di manipolazione dei dati simili. Questa pagina confronta i due approcci.

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

Il Data Manipulation Language (DML) in Spanner ti consente di manipolare i dati nelle tabelle di database utilizzando le istruzioni INSERT, UPDATE e DELETE. Puoi eseguire istruzioni DML utilizzando le librerie client, la console Google Cloud e gcloud spanner.

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

  • DML standard: adatto per carichi di lavoro standard di elaborazione delle transazioni online (OLTP).

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

  • DML partizionato: progettato per aggiornamenti ed eliminazione collettivi, come negli esempi che seguono.

    • Pulizia periodica e garbage collection. Ad esempio, puoi eliminare le vecchie righe o impostare le colonne su NULL.

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

    Per ulteriori informazioni, inclusi gli esempi di codice, consulta la sezione Utilizzo di DML partizionato.

    Puoi utilizzare le scritture batch per un numero elevato di operazioni di scrittura senza operazioni di lettura che non richiedono transazioni atomiche. Per maggiori informazioni, consulta Modificare i dati tramite scritture batch.

Cosa sono le mutazioni?

Una mutazione rappresenta una sequenza di inserti, aggiornamenti ed eliminazioni che Spanner applica a livello atomico alle diverse righe e tabelle di un database. Puoi includere modifiche che si applicano a righe o tabelle diverse. 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 maggiori informazioni, inclusi gli esempi di codice, consulta Inserire, aggiornare ed eliminare i dati utilizzando le mutazioni.

Confronto delle funzionalità tra DML e mutazioni

La seguente tabella riassume il supporto di DML e della modifica delle funzionalità e delle operazioni comuni del database.

Suite operativa DML Mutazioni
Inserisci dati Supportato Supportato
Elimina dati Supportato Supportato
Aggiorna dati Supportato Supportato
Inserisci o ignora dati Supportato Non supportato
Leggi le tue scritture (RYW) Supportato Non supportato
Inserisci o aggiorna dati (upsert) Supportato Supportato
Sintassi SQL Supportato Non supportato
Controllo dei vincoli Dopo ogni estratto conto Al momento del commit

DML e mutazioni divergono nel supporto delle seguenti funzionalità:

  • Read Your Writes: per leggere i risultati di cui non è stato eseguito il commit all'interno di una transazione attiva. Le modifiche apportate utilizzando le istruzioni DML sono visibili alle istruzioni successive nella stessa transazione. Ciò è diverso dall'uso delle mutazioni, in cui le modifiche non sono visibili in nessuna lettura (incluse le letture eseguite nella stessa transazione) fino a quando la transazione non viene confermata. Questo perché le mutazioni in una transazione vengono memorizzate nel buffer lato client (a livello locale) e vengono 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. È diverso dall'utilizzo delle mutazioni, in cui Spanner memorizza le mutazioni nel 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.

  • Sintassi SQL: DML offre 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 mutazione nella stessa transazione

Se una transazione contiene sia istruzioni DML sia modifiche 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 tua libreria client, devi utilizzare istruzioni DML o le mutazioni in una singola transazione, ma non entrambe.

L'esempio Java riportato di seguito illustra un comportamento potenzialmente sorprendente. Il codice inserisce due righe negli album utilizzando l'API Mutation. Lo snippet, poi chiama 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 dovessi eseguire questo codice, vedrai 0 record aggiornati. Perché? Questo accade perché le modifiche apportate utilizzando le modifiche non sono visibili alle istruzioni successive fino a quando la transazione non viene confermata. Idealmente, dovremmo eseguire il buffer delle scritture solo alla fine della transazione.

Che cosa succede dopo?