Il Data Manipulation Language partizionato (DML partizionato) è progettato per i seguenti tipi di aggiornamenti ed eliminazioni collettivi:
- 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
UPDATEper impostare il valore di una nuova colonna suFalsequando è attualmenteNULL.
Il DML partizionato non è adatto all'elaborazione delle transazioni su piccola scala. Se vuoi eseguire un'istruzione su alcune righe, utilizza i DML transazionali con chiavi primarie identificabili. Per saperne di più, consulta Utilizzo di DML.
Se devi eseguire il commit di un numero elevato di scritture cieche, ma non hai bisogno di una transazione atomica, puoi modificare collettivamente le tabelle Spanner utilizzando la scrittura batch. Per saperne di più, consulta Modificare i dati utilizzando le scritture batch.
Puoi ottenere approfondimenti sulle query DML partizionate attive e sui relativi progressi dalle tabelle delle statistiche nel database Spanner. Per saperne di più, consulta Statistiche DML partizionate attive.
DML e DML partizionato
Spanner supporta due modalità di esecuzione per le istruzioni DML:
DML, adatto all'elaborazione delle transazioni. Per saperne di più, consulta Utilizzo di DML.
DML partizionato, che consente operazioni su larga scala a livello di database con un impatto minimo sull'elaborazione delle transazioni simultanee mediante il partizionamento dello spazio delle chiavi e l'esecuzione dell'istruzione sulle partizioni in transazioni separate con ambito più piccolo. Per saperne di più, consulta Utilizzo di DML partizionato.
La tabella seguente evidenzia alcune delle differenze tra le due modalità di esecuzione.
| DML | DML partizionato |
|---|---|
Le righe che non corrispondono alla clausola WHERE potrebbero essere bloccate. |
Vengono bloccate solo le righe che corrispondono alla clausola WHERE. |
| Si applicano i limiti di dimensione delle transazioni. | Spanner gestisce i limiti delle transazioni e i limiti di concorrenza per transazione. |
| Le istruzioni non devono essere idempotenti. | Un'istruzione DML deve essere idempotente per garantire risultati coerenti. |
| Una transazione può includere più istruzioni DML e SQL. | Una transazione partizionata può includere una sola istruzione DML. |
| Non esistono restrizioni sulla complessità delle istruzioni. | Le istruzioni devono essere completamente partizionabili. |
| Crei transazioni di lettura/scrittura nel codice client. | Spanner crea le transazioni. |
Partizionabile e idempotente
Quando viene eseguita un'istruzione DML partizionata, le righe di una partizione non hanno accesso alle righe di altre partizioni e non puoi scegliere in che modo Spanner crea le partizioni. Il partizionamento garantisce la scalabilità, ma significa anche che le istruzioni DML partizionate devono essere completamente partizionabili. Ovvero, l'istruzione DML partizionata deve essere esprimibile come l'unione di un insieme di istruzioni, in cui ogni istruzione accede a una singola riga della tabella e ogni istruzione non accede ad altre tabelle. Ad esempio, un'istruzione DML che accede a più tabelle o esegue un self-join non è partizionabile. Se l'istruzione DML non è partizionabile, Spanner restituisce l'errore BadUsage.
Queste istruzioni DML sono completamente partizionabili, perché ogni istruzione può essere applicata a una singola riga della tabella:
UPDATE Singers SET LastName = NULL WHERE LastName = '';
DELETE FROM Albums WHERE MarketingBudget > 10000;
Questa istruzione DML non è completamente partizionabile, perché accede a più tabelle:
# Not fully partitionable
DELETE FROM Singers WHERE
SingerId NOT IN (SELECT SingerId FROM Concerts);
Spanner potrebbe eseguire un'istruzione DML partizionata più volte su alcune partizioni a causa di nuovi tentativi a livello di rete. Di conseguenza, un'istruzione potrebbe essere eseguita più di una volta su una riga. L'istruzione deve quindi essere idempotente per produrre risultati coerenti. Un'istruzione è idempotente se la sua esecuzione più volte su una singola riga porta allo stesso risultato.
Questa istruzione DML è idempotente:
UPDATE Singers SET MarketingBudget = 1000 WHERE true;
Questa istruzione DML non è idempotente:
UPDATE Singers SET MarketingBudget = 1.5 * MarketingBudget WHERE true;
Eliminare righe dalle tabelle principali con tabelle secondarie indicizzate
Quando utilizzi un'istruzione DML partizionata per eliminare righe in una tabella principale, l'
operazione potrebbe non riuscire e generare l'errore: The transaction contains too many
mutations. Questo si verifica se la tabella principale ha tabelle secondarie interleaved che contengono un indice globale. Le mutazioni alle righe della tabella secondaria non vengono
conteggiate rispetto al limite di mutazione della transazione.
Tuttavia, vengono conteggiate le mutazioni corrispondenti alle voci dell'indice. Se viene interessato un numero elevato di voci dell'indice della tabella secondaria, la transazione potrebbe superare il limite di mutazione.
Per evitare questo errore, elimina le righe in due istruzioni DML partizionate separate:
- Esegui un'eliminazione partizionata sulle tabelle secondarie.
- Esegui un'eliminazione partizionata sulla tabella principale.
Questo processo in due passaggi consente di mantenere il conteggio delle mutazioni entro i limiti consentiti per ogni transazione. In alternativa, puoi eliminare l'indice globale nella tabella secondaria prima di eliminare le righe principali.
Blocco delle righe
Spanner acquisisce un blocco solo se una riga è candidata per l'aggiornamento o l'eliminazione. Questo comportamento è diverso dall'
esecuzione DML, che potrebbe bloccare in lettura
le righe che non corrispondono alla clausola WHERE.
Esecuzione e transazioni
Se un'istruzione DML è partizionata o meno dipende dal metodo della libreria client scelto per l'esecuzione. Ogni libreria client fornisce metodi separati per l'esecuzione DML e l'esecuzione DML partizionata.
Puoi eseguire una sola istruzione DML partizionata in una chiamata al metodo della libreria client.
Spanner non applica le istruzioni DML partizionate in modo atomico all'intera tabella. Tuttavia, Spanner applica le istruzioni DML partizionate in modo atomico a ogni partizione.
Il DML partizionato non supporta il commit o il rollback. Spanner esegue e applica immediatamente l'istruzione DML.
- Se annulli l'operazione, Spanner annulla le partizioni in esecuzione e non avvia le partizioni rimanenti. Spanner non esegue il rollback delle partizioni già eseguite.
- Se l'esecuzione dell'istruzione genera un errore, l'esecuzione si interrompe in tutte le partizioni e Spanner restituisce l'errore per l'intera operazione. Alcuni esempi di errori sono violazioni dei vincoli del tipo di dati
, violazioni di
UNIQUE INDEXe violazioni diON DELETE NO ACTION. A seconda del momento in cui l'esecuzione non è riuscita, l'istruzione potrebbe essere stata eseguita correttamente su alcune partizioni e potrebbe non essere mai stata eseguita su altre partizioni.
Se l'istruzione DML partizionata ha esito positivo, Spanner ha eseguito l'istruzione almeno una volta su ogni partizione dell'intervallo di chiavi.
Conteggio delle righe modificate
Un'istruzione DML partizionata restituisce un limite inferiore al numero di righe modificate. Potrebbe non essere un conteggio esatto del numero di righe modificate, perché non è garantito che Spanner conteggi tutte le righe modificate.
Limiti transazioni
Spanner crea le partizioni e le transazioni necessarie per eseguire un'istruzione DML partizionata. Si applicano i limiti delle transazioni o i limiti di concorrenza per transazione, ma Spanner tenta di mantenere le transazioni entro i limiti.
Spanner consente un massimo di 20.000 istruzioni DML partizionate simultanee per database.
Funzionalità non supportate
Spanner non supporta alcune funzionalità per il DML partizionato:
INSERTnon è supportato.- Google Cloud Console: non puoi eseguire istruzioni DML partizionate nella Google Cloud console.
- Piani di query e profilazione: Google Cloud CLI e le librerie client non supportano i piani di query e la profilazione.
- Subquery che leggono da un'altra tabella o da una riga diversa della stessa tabella.
Per scenari complessi, come lo spostamento di una tabella o le trasformazioni che richiedono join tra tabelle, valuta la possibilità di utilizzare il connettore Dataflow.
Best practice
Applica le seguenti best practice per migliorare il rendimento delle istruzioni DML partizionate:
- Evita la concorrenza elevata: l'esecuzione simultanea di un numero elevato di istruzioni DML partizionate (ad esempio, più di 100) potrebbe causare conflitti di blocco nelle tabelle di sistema interne, peggiorando il rendimento. Anziché eseguire un numero elevato di istruzioni simultanee, utilizza una singola istruzione DML partizionata.
- Utilizza
PDML_MAX_PARALLELISM: per aumentare la velocità effettiva di una singola istruzione DML partizionata, soprattutto nelle tabelle con molte suddivisioni, imposta un valore più alto per l'PDML_MAX_PARALLELISMhint dell'istruzione. In questo modo, la singola istruzione può utilizzare più parallelismo internamente. L'impostazione di un valore più alto perPDML_MAX_PARALLELISMcomporta un maggiore utilizzo di risorse di calcolo, quindi devi cercare di bilanciare l'utilizzo di risorse di calcolo e l'aumento della velocità di elaborazione. - Consenti a Spanner di gestire il partizionamento: evita di eseguire manualmente lo sharding dei dati (ad esempio, utilizzando intervalli di chiave primaria) ed eseguire istruzioni DML partizionate separate su ogni shard. Il DML partizionato è progettato per partizionare in modo efficiente il lavoro su tutta la tabella. Lo sharding personalizzato spesso aumenta il sovraccarico e potrebbe peggiorare i conflitti.
- Comprendi l'ambito del partizionamento: le operazioni DML partizionate vengono parallelizzate su tutte le suddivisioni dell'intero database, non solo sulle suddivisioni contenenti i dati della tabella da modificare. Ciò significa che per i database con un numero elevato di suddivisioni, potrebbe esserci un sovraccarico anche se la tabella di destinazione è piccola o i dati modificati sono localizzati. Il DML partizionato potrebbe non essere la scelta più efficiente per modificare una porzione molto piccola di un database di grandi dimensioni.
- Valuta alternative per eliminazioni piccole e frequenti: per i casi d'uso che prevedono eliminazioni frequenti di un numero ridotto di righe note, l'utilizzo di istruzioni DML all'interno delle transazioni o dell'API BatchWrite potrebbe offrire un rendimento migliore e un sovraccarico inferiore rispetto all'utilizzo del DML partizionato.
Esempi
Il seguente esempio di codice aggiorna la colonna MarketingBudget della tabella Albums.
C++
Utilizza la funzione ExecutePartitionedDml() per eseguire un'istruzione DML partizionata.
C#
Utilizza il metodo ExecutePartitionedUpdateAsync() per eseguire un'istruzione DML partizionata.
Vai
Utilizza il metodo PartitionedUpdate() per eseguire un'istruzione DML partizionata.
Java
Utilizza il metodo executePartitionedUpdate() per eseguire un'istruzione DML partizionata.
Node.js
Utilizza il metodo runPartitionedUpdate() per eseguire un'istruzione DML partizionata.
PHP
Utilizza il metodo executePartitionedUpdate() per eseguire un'istruzione DML partizionata.
Python
Utilizza il metodo execute_partitioned_dml() per eseguire un'istruzione DML partizionata.
Ruby
Utilizza il metodo execute_partitioned_update() per eseguire un'istruzione DML partizionata.
Il seguente esempio di codice elimina le righe dalla tabella Singers, in base alla colonna SingerId.
C++
C#
Vai
Java
Node.js
PHP
Python
Ruby
Passaggi successivi
Scopri come modificare i dati utilizzando DML.
Scopri le best practice per il Data Manipulation Language (DML).
Per scoprire le differenze tra DML e mutazioni, consulta Confrontare DML e mutazioni.
Valuta la possibilità di utilizzare il connettore Dataflow per altri scenari di trasformazione dei dati.