Best practice per il linguaggio Data Manipulation Language

Questa pagina descrive le best practice per l'utilizzo di Data Manipulation Language (DML) e DML partizionato.

Usa una clausola WHERE per ridurre l'ambito dei blocchi

Puoi eseguire istruzioni DML all'interno di transazioni di lettura-scrittura. Quando Spanner legge i dati, acquisisce blocchi di lettura condivisi su parti limitate degli intervalli di righe che leggi. In particolare, acquisisce questi blocchi solo sulle colonne a cui accedi. I blocchi possono includere dati che non soddisfano la condizione di filtro della clausola WHERE.

Quando Spanner modifica i dati utilizzando istruzioni DML, acquisisce blocchi esclusivi sui dati specifici che stai modificando. Inoltre, acquisisce i blocchi condivisi nello stesso modo in cui leggi i dati. Se la richiesta include intervalli di righe ampi o un'intera tabella, i blocchi condivisi potrebbero impedire l'avanzamento in parallelo di altre transazioni.

Per modificare i dati nel modo più efficiente possibile, utilizza una clausola WHERE che consenta a Spanner di leggere solo le righe necessarie. Puoi raggiungere questo obiettivo con un filtro sulla chiave primaria o sulla chiave di un indice secondario. La clausola WHERE limita l'ambito dei blocchi condivisi e consente a Spanner di elaborare l'aggiornamento in modo più efficiente.

Ad esempio, supponiamo che uno dei musicisti nella tabella Singers cambi il suo nome e che tu debba aggiornare il nome nel tuo database. Potresti eseguire la seguente istruzione DML, ma forza Spanner a scansionare l'intera tabella e acquisire blocchi condivisi che coprono l'intera tabella. Di conseguenza, Spanner deve leggere più dati del necessario e le transazioni simultanee non possono modificare i dati in parallelo:

-- 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";

Per rendere più efficiente l'aggiornamento, includi la colonna SingerId nella clausola WHERE. La colonna SingerId è l'unica colonna di chiave primaria per la tabella Singers:

-- ANTI-PATTERN: SENDING AN UPDATE THAT MUST SCAN THE ENTIRE TABLE

UPDATE Singers SET FirstName = "Marcel"
WHERE FirstName = "Marc" AND LastName = "Richards"

Se non è presente alcun indice su FirstName o LastName, devi analizzare l'intera tabella per trovare i cantanti target. Se non vuoi aggiungere un indice secondario per rendere più efficiente l'aggiornamento, includi la colonna SingerId nella clausola WHERE.

La colonna SingerId è l'unica colonna di chiave primaria per la tabella Singers. Per trovarlo, esegui SELECT in una transazione separata di sola lettura prima della transazione di aggiornamento:


  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;

Evita di utilizzare istruzioni DML e mutazioni nella stessa transazione

Spanner inserisce nel buffer le operazioni di inserimento, aggiornamento ed eliminazione eseguite utilizzando le istruzioni DML sul lato server. I risultati sono visibili alle successive istruzioni SQL e DML all'interno della stessa transazione. Questo comportamento è diverso dall'API Mutation, in cui Spanner memorizza le mutazioni sul lato client e invia le mutazioni sul lato 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.

Evita di utilizzare istruzioni DML e mutazioni nella stessa transazione. Se li utilizzi entrambi nella stessa transazione, devi tenere conto dell'ordine di esecuzione nel codice della libreria client. Se una transazione contiene sia istruzioni DML sia mutazioni nella stessa richiesta, Spanner esegue le istruzioni DML prima delle mutazioni.

Per le operazioni supportate solo con le mutazioni, ti consigliamo di combinare le istruzioni e le mutazioni DML nella stessa transazione, ad esempio insert_or_update.

Se utilizzi entrambi, il buffer scriverà solo alla fine della transazione.

Utilizza la funzione PENDING_COMMIT_TIMESTAMP per scrivere timestamp di commit

GoogleSQL

Puoi usare la funzione PENDING_COMMIT_TIMESTAMP per scrivere il timestamp di commit in un'istruzione DML. Spanner seleziona il timestamp di commit quando viene eseguito il commit della transazione.

PostgreSQL

Puoi usare la funzione SPANNER.PENDING_COMMIT_TIMESTAMP() per scrivere il timestamp di commit in un'istruzione DML. Spanner seleziona il timestamp di commit quando viene eseguito il commit della transazione.

DML partizionato e funzioni di data e timestamp

Il DML partizionato utilizza una o più transazioni di cui potrebbe essere eseguita l'esecuzione e il commit in momenti diversi. Se utilizzi le funzioni date o timestamp, le righe modificate potrebbero contenere valori diversi.

Migliora la latenza con DML in modalità batch

Per ridurre la latenza, utilizza DML in batch per inviare più istruzioni DML a Spanner in un singolo round trip client-server.

Batch DML può applicare ottimizzazioni a gruppi di istruzioni all'interno di un batch per consentire aggiornamenti dei dati più rapidi ed efficienti.

  • Esecuzione delle scritture con una singola richiesta

    Spanner ottimizza automaticamente gruppi contigui di istruzioni in batch INSERT, UPDATE o DELETE simili che hanno valori parametro diversi, se non violano le dipendenze dei dati.

    Ad esempio, considera uno scenario in cui vuoi inserire un grande insieme di nuove righe in una tabella denominata Albums. Per consentire a Spanner di ottimizzare tutte le istruzioni INSERT richieste in un'unica azione lato server efficiente, inizia scrivendo un'istruzione DML appropriata che utilizzi i parametri di query SQL:

    INSERT INTO Albums (SingerId, AlbumId, AlbumTitle) VALUES (@Singer, @Album, @Title);
    

    Quindi, invia a Spanner un batch DML che richiama questa istruzione in modo ripetuto e contiguo, con ripetizioni diverse solo per i valori associati ai tre parametri di ricerca dell'istruzione. Spanner ottimizza queste istruzioni DML strutturalmente identiche in un'unica operazione lato server prima di eseguirle.

  • Esegui scritture in parallelo

    Spanner ottimizza automaticamente gruppi contigui di istruzioni DML eseguendo l'esecuzione in parallelo senza violare le dipendenze dei dati. Questa ottimizzazione offre vantaggi in termini di prestazioni a un insieme più ampio di istruzioni DML in batch, perché può essere applicata a una combinazione di tipi di istruzione DML (INSERT, UPDATE e DELETE) e a istruzioni DML con o senza parametri.

    Ad esempio, il nostro schema di esempio ha le tabelle Singers, Albums e Accounts. Albums è interlacciato all'interno di Singers e memorizza le informazioni sugli album per Singers. Il seguente gruppo di istruzioni contigue scrive nuove righe in più tabelle e non ha dipendenze complesse dei dati.

    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;
    

    Spanner ottimizza questo gruppo di istruzioni DML eseguendo le istruzioni in parallelo. Le operazioni di scrittura vengono applicate in ordine di istruzione nel batch e mantengono la semantica DML batch se un'istruzione non va a buon fine durante l'esecuzione.