Spanner consente di aggiornare lo schema senza tempi di inattività. Puoi aggiornare lo schema di un database esistente in diversi modi:
Nella console Google Cloud
Invia un comando
ALTER TABLE
nella pagina Spanner Studio.Per accedere alla pagina Spanner Studio, fai clic su Spanner Studio dalla alla pagina Panoramica del database o Panoramica della tabella.
Utilizzo dello strumento a riga di comando
gcloud spanner
Invia un comando
ALTER TABLE
utilizzandogcloud spanner databases ddl update
.Utilizzare le librerie client
Utilizzare l'API REST di
projects.instances.databases.updateDdl
Utilizzo dell'API RPC di
UpdateDatabaseDdl
Aggiornamenti dello schema supportati
Spanner supporta i seguenti aggiornamenti dello schema di un database esistente:
- Aggiungi o rilascia uno schema denominato.
- Crea una nuova tabella. Le colonne nelle nuove tabelle possono essere
NOT NULL
. - Elimina una tabella se non ci sono altre tabelle con interleaving al suo interno e non è presente indici secondari.
- Crea o elimina una tabella con una chiave esterna.
- Aggiungi o rimuovi una chiave esterna da una tabella esistente.
- Aggiungi una colonna non chiave a qualsiasi tabella. Le nuove colonne non chiave non possono essere
NOT NULL
. - Trascina una colonna non chiave da qualsiasi tabella, a meno che non venga utilizzata da un indice secondario, chiave esterna, archiviata generata colonna o verifica il vincolo.
- Aggiungi
NOT NULL
a una colonna non chiave, escluse le colonneARRAY
. - Rimuovi
NOT NULL
da una colonna non chiave. - Modifica una colonna
STRING
in una colonnaBYTES
o una colonnaBYTES
in una ColonnaSTRING
. - Modifica una colonna
PROTO
in una colonnaBYTES
o una colonnaBYTES
in una ColonnaPROTO
. - Modifica il tipo di messaggio di protocollo di una colonna
PROTO
. - Aggiungi nuovi valori a una definizione di
ENUM
e rinomina i valori esistenti utilizzandoALTER PROTO BUNDLE
. - Modifica i messaggi definiti in un
PROTO BUNDLE
in modi arbitrari, a condizione che i campi modificati di questi messaggi non vengano utilizzati come chiavi in nessuna tabella e che i dati esistenti soddisfino i nuovi vincoli. - Aumenta o riduci il limite di lunghezza per un tipo
STRING
oBYTES
(incluso aMAX
), a meno che non è una colonna di chiave primaria ereditata da una o più tabelle figlio. - Aumenta o riduci il limite di lunghezza per
ARRAY<STRING>
,ARRAY<BYTES>
, oARRAY<PROTO>
fino al limite massimo consentito. - Attiva o disattiva i timestamp di commit in e le colonne di chiave primaria.
- Aggiungere o rimuovere un indice secondario.
- Aggiungi o rimuovi un vincolo di controllo da una tabella esistente.
- Aggiungi o rimuovi da una tabella esistente una colonna generata archiviata.
- Crea un nuovo pacchetto di statistiche di ottimizzazione.
- Creare e gestire le viste.
- Crea e gestisci le sequenze.
- Creare ruoli del database e concedere privilegi.
- Imposta, modifica o elimina il valore predefinito di una colonna.
- Modifica le opzioni del database (
default_leader
oversion_retention_period
ad esempio). - Creare e gestire i flussi di modifiche.
- Creare e gestire modelli di ML.
Aggiornamenti dello schema non supportati
Spanner non supporta i seguenti aggiornamenti dello schema di un modello esistente database:
- Se è presente un campo
PROTO
di tipoENUM
a cui fa riferimento un tabella o chiave indice, non puoi rimuovere i valoriENUM
dal protocollo enum. (Rimozione diENUM
valori dalle enumerazioni utilizzate daENUM<>
colonne sono supportate, anche quando queste colonne vengono utilizzate come chiavi.
Prestazioni dell'aggiornamento dello schema
Gli aggiornamenti dello schema in Spanner non richiedono tempi di inattività. Quando emetti un di istruzioni DDL in un database Spanner, puoi continuare a scrivere e leggere dal database senza interruzioni mentre Spanner si applica l'aggiornamento come operazione a lunga esecuzione.
Il tempo necessario per eseguire un'istruzione DDL dipende dal fatto che l'aggiornamento
richiede la convalida dei dati esistenti o il backfill di eventuali dati. Ad esempio:
Se aggiungi l'annotazione NOT NULL
a una colonna esistente, Spanner deve:
leggi tutti i valori della colonna per assicurarti che non contenga
qualsiasi valore NULL
. Questo passaggio può richiedere molto tempo se sono disponibili molti dati
valida. Un altro esempio è se aggiungi un indice a un database:
Spanner esegue il backfill dell'indice utilizzando i dati esistenti e questo processo può
richiedere molto tempo, a seconda di come la definizione dell'indice e la dimensione
tabella di base corrispondente. Tuttavia, se aggiungi una nuova colonna a una tabella,
nessun dato esistente da convalidare, quindi Spanner può rendere più efficace l'aggiornamento
rapidamente.
In sintesi, gli aggiornamenti dello schema che non richiedono Spanner per la convalida e quelli esistenti possono essere generati in pochi minuti. Aggiornamenti dello schema che richiedono la convalida può richiedere più tempo, a seconda della quantità di dati esistenti che deve essere ma la convalida dei dati avviene in background con una priorità più bassa rispetto al traffico di produzione. Gli aggiornamenti dello schema che richiedono la convalida dei dati più approfonditamente nella prossima sezione.
Aggiornamenti dello schema convalidati in base alle definizioni delle viste
Quando esegui un aggiornamento dello schema, Spanner verifica che l'aggiornamento le query utilizzate per definire le viste esistenti non verranno annullate. Se la convalida è riuscito, l'aggiornamento dello schema è andato a buon fine. Se la convalida non ha esito positivo, l'aggiornamento dello schema non va a buon fine. Controllo Best practice per la creazione di viste per i dettagli.
Aggiornamenti dello schema che richiedono la convalida dei dati
Puoi apportare aggiornamenti allo schema che richiedono la convalida dei dati esistenti che soddisfi i nuovi vincoli. Quando un aggiornamento dello schema richiede la convalida dei dati, Spanner non consente gli aggiornamenti dello schema in conflitto nello schema interessato le entità e convalida i dati in background. Se la convalida ha esito positivo, l'aggiornamento dello schema è andato a buon fine. Se la convalida non ha esito positivo, lo schema viene aggiornato non riesce. Le operazioni di convalida vengono eseguite operative a lunga esecuzione. Puoi controlla lo stato di queste operazioni per capire se sono riuscite o non riuscite.
Ad esempio, supponi di aver definito il seguente file music.proto
con un
RecordLabel
enum e Songwriter
messaggio di protocollo:
enum RecordLabel {
COOL_MUSIC_INC = 0;
PACIFIC_ENTERTAINMENT = 1;
XYZ_RECORDS = 2;
}
message Songwriter {
required string nationality = 1;
optional int64 year_of_birth = 2;
}
Per aggiungere una tabella Songwriters
allo schema:
GoogleSQL
CREATE PROTO BUNDLE (
googlesql.example.music.Songwriter,
googlesql.example.music.RecordLabel,
);
CREATE TABLE Songwriters (
Id INT64 NOT NULL,
FirstName STRING(1024),
LastName STRING(1024),
Nickname STRING(MAX),
OpaqueData BYTES(MAX),
SongWriter googlesql.example.music.Songwriter
) PRIMARY KEY (Id);
CREATE TABLE Albums (
SongwriterId INT64 NOT NULL,
AlbumId INT64 NOT NULL,
AlbumTitle STRING(MAX),
Label INT32
) PRIMARY KEY (SongwriterId, AlbumId);
I seguenti aggiornamenti dello schema sono consentiti, ma richiedono la convalida e potrebbero il completamento dell'operazione richiede più tempo, a seconda della quantità di dati esistenti:
Aggiunta dell'annotazione
NOT NULL
a una colonna non chiave. Ad esempio:ALTER TABLE Songwriters ALTER COLUMN Nickname STRING(MAX) NOT NULL;
Ridurre la lunghezza di una colonna. Ad esempio:
ALTER TABLE Songwriters ALTER COLUMN FirstName STRING(10);
Modifica in corso da
BYTES
aSTRING
. Ad esempio:ALTER TABLE Songwriters ALTER COLUMN OpaqueData STRING(MAX);
Modifica in corso da
INT64/INT32
aENUM
. Ad esempio:ALTER TABLE Albums ALTER COLUMN Label googlesql.example.music.RecordLabel;
Rimozione dei valori esistenti dalla definizione enum
RecordLabel
.Attivazione dei timestamp di commit in una colonna
TIMESTAMP
esistente. Ad esempio:ALTER TABLE Albums ALTER COLUMN LastUpdateTime SET OPTIONS (allow_commit_timestamp = true);
Aggiunta di un vincolo di controllo a una tabella esistente.
Aggiunta di una colonna generata archiviata a una tabella esistente.
Creazione di una nuova tabella con una chiave esterna.
Aggiunta di una chiave esterna a una tabella esistente.
Questi aggiornamenti dello schema non riescono se i dati sottostanti non soddisfano i nuovi
i vincoli. Ad esempio, l'istruzione ALTER TABLE Songwriters ALTER COLUMN Nickname
STRING(MAX) NOT NULL
ha esito negativo se viene fornito qualsiasi valore nell'attributo Nickname
è NULL
, perché i dati esistenti non soddisfano i NOT NULL
vincolo della nuova definizione.
La convalida dei dati può richiedere da diversi minuti a molte ore. L'ora di La convalida completa dei dati dipende da:
- La dimensione del set di dati
- La capacità di calcolo dell'istanza
- Il carico sull'istanza
Alcuni aggiornamenti dello schema possono modificare il comportamento delle richieste al database prima
l'aggiornamento dello schema è stato completato. Ad esempio, se aggiungi NOT NULL
a una
Spanner inizia quasi immediatamente a rifiutare le scritture per i nuovi
richieste che utilizzano NULL
per la colonna. Se il nuovo schema viene aggiornato
non riesce per la convalida dei dati, ci sarà stato un periodo di tempo in cui le scritture
sono stati bloccati, anche se sarebbero stati accettati dallo schema precedente.
Puoi annullare un'operazione di convalida dei dati a lunga esecuzione utilizzando
projects.instances.databases.operations.cancel
o l'utilizzo di
gcloud spanner operations
.
Ordine di esecuzione delle istruzioni in batch
Se utilizzi Google Cloud CLI, l'API REST o l'API RPC, puoi inviare
di una o più istruzioni CREATE
, ALTER
o DROP
.
Spanner applica in ordine le istruzioni dello stesso batch, fermandosi al primo errore. Se l'applicazione di un'istruzione genera un errore, l'istruzione viene eseguito il rollback. I risultati di eventuali istruzioni applicate in precedenza nel batch. non vengono sottoposti a rollback.
Spanner potrebbe combinare e riordinare le istruzioni di diversi batch,
potenzialmente combinare istruzioni di diversi batch in un'unica modifica atomica
viene applicata al database. All'interno di ogni modifica atomica,
che avvengono in un ordine arbitrario. Ad esempio, se un gruppo di istruzioni
contiene ALTER TABLE MyTable ALTER COLUMN MyColumn STRING(50)
e un altro
di istruzioni contiene ALTER TABLE MyTable ALTER COLUMN MyColumn
STRING(20)
, Spanner lascerà la colonna in uno di questi due stati,
ma non è specificato quale.
Versioni di schema create durante gli aggiornamenti dello schema
Spanner utilizza il controllo delle versioni dello schema per evitare tempi di inattività durante lo schema a un database di grandi dimensioni. Spanner mantiene lo schema precedente per supportare le letture durante l'elaborazione dell'aggiornamento dello schema. Spanner vengono quindi create una o più nuove versioni dello schema per elaborarlo aggiornamento. Ogni versione contiene il risultato di una raccolta di istruzioni in un una singola modifica atomica.
Le versioni dello schema non corrispondono necessariamente uno a uno con i due batch di istruzioni DDL o singole istruzioni DDL. Alcune singole istruzioni DDL, come la creazione di indici per tabelle di base o istruzioni esistenti che richiedono dati la convalida comporta la creazione di più versioni dello schema. In altri casi, diversi DDL le istruzioni possono essere raggruppate in un'unica versione. Le versioni precedenti dello schema possono consumano notevoli risorse di server e archiviazione e vengono conservate fino scadono (non sono più necessarie per pubblicare letture delle versioni precedenti dei dati).
La tabella seguente mostra il tempo necessario a Spanner per aggiornare uno schema.
Operazione dello schema | Durata stimata |
---|---|
CREATE TABLE |
Minuti |
CREATE INDEX |
Da minuti a ore, se la tabella di base viene creata prima dell'indice. Minuti, se l'istruzione viene eseguita contemporaneamente all'istruzione |
DROP TABLE |
Minuti |
DROP INDEX |
Minuti |
ALTER TABLE ... ADD COLUMN |
Minuti |
ALTER TABLE ... ALTER COLUMN |
Da minuti a ore, se è richiesta la convalida in background. Minuti, se la convalida in background non è richiesta. |
ALTER TABLE ... DROP COLUMN |
Minuti |
ANALYZE |
Da minuti a ore, a seconda della dimensione del database. |
Modifiche ai tipi di dati e modifiche in tempo reale
Se modifichi il tipo di dati di una colonna che modifica
Stream, il campo column_types
del flusso di modifiche successivo pertinente
record
riflette il nuovo tipo, così come i dati JSON old_values
all'interno
record mods
.
Il valore new_values
del campo mods
di un record di modifiche in tempo reale corrisponde sempre
il tipo corrente di una colonna. La modifica del tipo di dati di una colonna controllata
influire su eventuali record delle modifiche in tempo
antecedenti a tale modifica.
Nel caso specifico di una variazione da BYTES
a STRING
,
Spanner convalida il valore precedente della colonna
nell'ambito dell'aggiornamento dello schema.
Di conseguenza, Spanner ha decodificato in modo sicuro il vecchio
Quando scrive i valori successivi, inseriscili in stringhe con BYTES
.
record delle modifiche in tempo reale.
Best practice per gli aggiornamenti dello schema
Le seguenti sezioni descrivono le best practice per l'aggiornamento degli schemi.
Procedure precedenti all'aggiornamento dello schema
Prima di eseguire un aggiornamento dello schema:
Verifica che tutti i dati esistenti nel database che stai modificando soddisfa i vincoli imposti dall'aggiornamento dello schema. Poiché il successo di alcuni tipi di aggiornamenti dello schema dipendono dai dati nel database e non solo allo schema attuale, un aggiornamento dello schema riuscito di un database di test garantire il corretto aggiornamento dello schema di un database di produzione. Ecco alcuni esempi esempi comuni:
- Se aggiungi un'annotazione
NOT NULL
a una colonna esistente, verifica che: la colonna non contiene valoriNULL
esistenti. - Se intendi ridurre la lunghezza consentita di una colonna
STRING
oBYTES
, verifica che tutti i valori esistenti nella colonna corrispondano alla lunghezza di blocco.
- Se aggiungi un'annotazione
Se stai scrivendo su una colonna, una tabella o un indice sottoposto a uno schema aggiorna, assicurati che i valori che scrivi soddisfino i nuovi vincoli.
Se stai eliminando una colonna, una tabella o un indice, assicurati di non essere ancora leggere o scrivere messaggi.
Limitare la frequenza degli aggiornamenti dello schema
Se esegui troppi aggiornamenti dello schema in un breve periodo di tempo, Spanner
potrebbe throttle
degli aggiornamenti dello schema in coda. Questo perché Spanner limita
per archiviare le versioni dello schema. L'aggiornamento dello schema potrebbe essere limitato
se esistono troppe versioni precedenti dello schema nel periodo di conservazione. La
la frequenza massima di modifiche allo schema dipende da molti fattori,
uno dei quali è il numero totale di colonne nel database. Ad esempio, un
con 2000 colonne (circa 2000 righe
INFORMATION_SCHEMA.COLUMNS
)
è in grado di eseguire un massimo di 1500 modifiche allo schema (meno se lo schema
richiede più versioni) durante il periodo di conservazione. Per visualizzare lo stato
degli aggiornamenti dello schema in corso, utilizza
gcloud spanner operations list
e filtrarlo per operazioni di tipo DATABASE_UPDATE_DDL
. Per annullare un
è in corso l'aggiornamento dello schema,
gcloud spanner operations cancel
e specificare l'ID operazione.
Il modo in cui le istruzioni DDL vengono raggruppate e il relativo ordine all'interno di ogni batch può influisce sul numero di versioni dello schema risultanti. Per massimizzare il numero aggiornamenti dello schema che puoi eseguire in un determinato periodo di tempo, devi utilizzare che riduce al minimo il numero di versioni dello schema. Alcune regole empiriche sono descritti negli aggiornamenti di grandi dimensioni.
Come descritto nelle versioni dello schema, alcune istruzioni DDL creare più versioni dello schema, che sono importanti nel valutare raggrupparle e ordinarle all'interno di ogni batch. Esistono due tipi principali di istruzioni che potrebbero creare più versioni dello schema:
- Dichiarazioni che potrebbero richiedere il backfill dei dati dell'indice, ad esempio
CREATE INDEX
- Dichiarazioni che potrebbero richiedere la convalida di dati esistenti, come l'aggiunta di
NOT NULL
Questi tipi di istruzioni non creano sempre più versioni dello schema,
però. Spanner cercherà di rilevare quando questi tipi di istruzioni possono essere
ottimizzate per evitare di utilizzare più versioni dello schema, che dipende dal raggruppamento.
Ad esempio, un'istruzione CREATE INDEX
presente nello stesso batch di un'istruzione
Istruzione CREATE TABLE
per la tabella di base dell'indice, senza alcuna istruzione
per altre tabelle, evita di dover eseguire il backfill dei dati dell'indice
perché Spanner può garantire che la tabella di base sia vuota in quel momento
viene creato l'indice. La sezione relativa agli aggiornamenti di grandi dimensioni descrive come
di utilizzare questa proprietà per creare molti indici in modo efficiente.
Se non riesci a raggruppare le istruzioni DDL per evitare di creare molte versioni dello schema, devi limitare il numero di aggiornamenti dello schema allo schema di un singolo database nel periodo di conservazione. Aumenta l'intervallo di tempo entro il quale crei lo schema aggiornamenti per consentire a Spanner di rimuovere le versioni precedenti dello schema prima di vengono create.
- Per alcuni sistemi di gestione di database relazionali, esistono pacchetti software che effettuano una lunga serie di upgrade e downgrade dello schema al database su ogni deployment di produzione. Questi tipi di processi sono sconsigliati per Spanner.
- Spanner è ottimizzato per usare le chiavi primarie per eseguire il partizionamento dei dati per soluzioni multi-tenancy. Le soluzioni multi-tenancy che utilizzano tabelle separate per ciascun cliente possono in un grande backlog di operazioni di aggiornamento dello schema che richiedono completato.
- Gli aggiornamenti dello schema che richiedono la convalida o il backfill dell'indice utilizzano più server perché ogni istruzione crea più versioni dello schema internamente.
Opzioni per aggiornamenti di grandi dimensioni dello schema
Il modo migliore per creare una tabella e un numero elevato di indici al suo interno è crearle tutte contemporaneamente, in modo che ci sia un solo schema è stata creata la versione precedente. La best practice prevede di creare gli indici subito dopo la tabella nell'elenco delle istruzioni DDL. Puoi creare la tabella e i relativi quando si crea il database o in un singolo batch di grandi dimensioni di istruzioni. Se devi creare molte tabelle, ognuna con molti indici, puoi includere tutte le istruzioni in un singolo batch. Puoi includere diverse migliaia di istruzioni in in un singolo batch quando tutte le istruzioni possono essere eseguite insieme utilizzando della versione dello schema.
Quando un'istruzione richiede il backfill dei dati dell'indice o la convalida dei dati,
non può essere eseguito
in una singola versione dello schema. Questo accade per CREATE INDEX
quando la tabella di base dell'indice esiste già (perché era
creati in un batch precedente di istruzioni DDL o perché era presente
nel batch tra le istruzioni CREATE TABLE
e CREATE INDEX
che
necessarie più versioni dello schema). Spanner richiede che non ci siano
più di dieci istruzioni di questo tipo in un singolo batch. La creazione di indici che richiede
Il backfill, in particolare, utilizza diverse versioni dello schema per indice, pertanto
come regola generale creare non più di 3 nuovi
che richiedono il backfilling al giorno (indipendentemente da come vengono raggruppati, a meno che
il batch può evitare il backfill).
Ad esempio, questo gruppo di istruzioni utilizzerà una singola versione dello schema:
GoogleSQL
CREATE TABLE Singers ( SingerId INT64 NOT NULL, FirstName STRING(1024), LastName STRING(1024), ) PRIMARY KEY (SingerId); CREATE INDEX SingersByFirstName ON Singers(FirstName); CREATE INDEX SingersByLastName ON Singers(LastName); CREATE TABLE Albums ( SingerId INT64 NOT NULL, AlbumId INT64 NOT NULL, AlbumTitle STRING(MAX), ) PRIMARY KEY (SingerId, AlbumId); CREATE INDEX AlbumsByTitle ON Albums(AlbumTitle);
Al contrario, questo batch utilizzerà molte versioni dello schema, perché UnrelatedIndex
richiede il backfill (poiché la tabella di base deve essere già esistita)
obbliga tutti i seguenti indici a richiedere anche il backfill (anche se
sono nello stesso batch delle loro tabelle di base):
GoogleSQL
CREATE TABLE Singers ( SingerId INT64 NOT NULL, FirstName STRING(1024), LastName STRING(1024), ) PRIMARY KEY (SingerId); CREATE TABLE Albums ( SingerId INT64 NOT NULL, AlbumId INT64 NOT NULL, AlbumTitle STRING(MAX), ) PRIMARY KEY (SingerId, AlbumId); CREATE INDEX UnrelatedIndex ON UnrelatedTable(UnrelatedIndexKey); CREATE INDEX SingersByFirstName ON Singers(FirstName); CREATE INDEX SingersByLastName ON Singers(LastName); CREATE INDEX AlbumsByTitle ON Albums(AlbumTitle);
Sarebbe meglio portare alla fine della creazione di UnrelatedIndex
batch o in batch diversi, per ridurre al minimo le versioni dello schema.
Attendi il completamento delle richieste API
Quando crei projects.instances.databases.updateDdl
(REST
API) o UpdateDatabaseDdl
(API RPC), utilizza
projects.instances.databases.operations.get
(API REST)
o GetOperation
(API RPC), rispettivamente, per attendere
ogni richiesta da completare prima di avviarne una nuova. In attesa di ogni richiesta
consente alla tua applicazione di monitorare l'avanzamento dello schema
aggiornamenti. Inoltre, mantiene l'arretrato degli aggiornamenti dello schema in sospeso
dimensioni.
Caricamento collettivo
Se esegui il caricamento collettivo dei dati nelle tabelle dopo la loro creazione, di solito è più efficiente creare indici dopo aver caricato i dati. Se aggiungendo diversi indici, potrebbe essere più efficiente creare il database tutte le tabelle e gli indici nello schema iniziale, come descritto in opzioni per gli aggiornamenti di grandi dimensioni.