Questa pagina descrive le best practice per l'utilizzo di DML (Data Manipulation Language) e DML partizionata.
Usa una clausola WHERE per ridurre l'ambito dei blocchi
Esegui 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 nelle colonne a cui accedi. I blocchi possono includere dati che non
soddisfano le condizioni di filtro della clausola WHERE
.
Quando Spanner modifica i dati utilizzando istruzioni DML, acquisisce i blocchi esclusivi sui dati specifici che stai modificando. Inoltre, acquisisce i blocchi condivisi allo stesso modo quando leggi i dati. Se la richiesta include ampi intervalli di righe o un'intera tabella, i blocchi 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
i 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 tu debba aggiornare il nome nel database. Potresti eseguire il seguente DML
ma obbliga Spanner a scansionare l'intera tabella e ad acquisire blocchi condivisi che
per coprire 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 l'aggiornamento più efficiente, includi la colonna SingerId
nella clausola WHERE
. La colonna SingerId
è l'unica colonna della 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 in FirstName
o LastName
, devi
scansionare 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 di sola lettura distinta 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
Inserimenti, aggiornamenti ed eliminazioni del buffer di Spanner eseguiti utilizzando DML sul lato server e i risultati sono visibili alle successive istruzioni SQL Istruzioni DML all'interno della stessa transazione. Questo comportamento è diverso dall'API Mutation, in cui Spanner mette in buffer le mutazioni lato client e le invia 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 sia istruzioni DML che 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, potresti voler
combinare istruzioni DML e mutazioni nella stessa transazione, ad esempio
insert_or_update
Se utilizzi entrambi, il buffer scrive solo alla fine della transazione.
Utilizza la funzione PENDING_COMMIT_TIMESTAMP per scrivere i timestamp dei commit
GoogleSQL
Utilizzerai la funzione PENDING_COMMIT_TIMESTAMP
per scrivere il commit
in un'istruzione DML. Spanner seleziona il timestamp del commit al momento del commit della transazione.
PostgreSQL
Utilizza la funzione SPANNER.PENDING_COMMIT_TIMESTAMP()
per scrivere il timestamp del commit in un'istruzione DML. Spanner seleziona il timestamp del commit al momento del commit della transazione.
Funzioni DML partizionate e data e timestamp
Il DML partizionato utilizza una o più transazioni che possono essere eseguite e sottoposte a commit in momenti diversi. Se utilizzi date o timestamp le righe modificate potrebbero contenere valori diversi.
Migliora la latenza con DML batch
Per ridurre la latenza, utilizza la DML batch per inviare più istruzioni DML a Spanner in un unico round-trip client-server.
DML batch può applicare ottimizzazioni a gruppi di istruzioni all'interno di un batch per consentire aggiornamenti dei dati più rapidi ed efficienti.
Eseguire scritture con una singola richiesta
Spanner ottimizza automaticamente i gruppi contigui di istruzioni INSERT, UPDATE o DELETE simili con valori di parametro diversi, se non violano le dipendenze dei dati.
Ad esempio, considera uno scenario in cui vuoi inserire un grande insieme di nuovi righe in una tabella denominata
Albums
. Per consentire a Spanner di ottimizzare tutte le richiesteINSERT
in un'unica ed efficiente azione lato server, inizia scrivendo un'istruzione DML appropriata che utilizzi una query SQL parametri:INSERT INTO Albums (SingerId, AlbumId, AlbumTitle) VALUES (@Singer, @Album, @Title);
Quindi, invia a Spanner un batch DML che invoca questa istruzione più volte e in modo contiguo, con le ripetizioni che differiscono solo per i valori associati ai tre parametri di query dell'istruzione. Spanner ottimizza questi DML strutturalmente identici in una singola operazione lato server prima di eseguirla.
Eseguire le scritture in parallelo
Spanner ottimizza automaticamente gruppi contigui di istruzioni DML l'esecuzione in parallelo non violerebbe le dipendenze dei dati. Questa ottimizzazione apporta vantaggi in termini di prestazioni a un set più ampio di DML in batch perché può essere applicata a una combinazione di tipi di istruzione DML (INSERT, UPDATE ed DELETE) e su DML sia con parametri che senza parametri istruzioni.
Ad esempio, il nostro schema di esempio ha le tabelle
Singers
,Albums
eAccounts
.Albums
è interlacciato inSingers
e memorizza informazioni sugli album perSingers
. Il seguente gruppo contiguo di istruzioni scrive nuove righe in più tabelle e non ha dati complessi delle dipendenze.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 il comando istruzioni in parallelo. Le scritture vengono applicate nell'ordine delle istruzioni nel batch e mantengono la semantica DML batch se un'istruzione non va a buon fine durante l'esecuzione.