In un database Spanner, Spanner crea automaticamente un
indice per la chiave primaria di ogni tabella. Ad esempio, non devi fare nulla
per indicizzare la chiave primaria di Singers
, perché viene indicizzata automaticamente per te.
Puoi anche creare indici secondari per altre colonne. Aggiunta di un indirizzo IP
su una colonna rende più efficiente la ricerca dei dati al suo interno. Per
ad esempio, se devi cercare rapidamente un album per titolo,
crea un indice secondario su AlbumTitle
,
in modo che Spanner non debba analizzare l'intera tabella.
Se la ricerca nell'esempio precedente viene eseguita all'interno di una transazione di lettura/scrittura,
una ricerca più efficiente evita anche di bloccare blocchi sull'intera tabella,
che consente l'inserimento e l'aggiornamento simultanei della tabella per le righe al di fuori del campo
Intervallo di ricerca AlbumTitle
.
Oltre ai vantaggi che offrono per le ricerche, gli indici secondari possono anche aiutare Spanner a eseguire le letture in modo più efficiente, attivando le letture dell'indice anziché le letture complete della tabella.
Spanner memorizza i seguenti dati in ogni indice secondario:
- Tutte le colonne principali della tabella di base
- Tutte le colonne incluse nell'indice
- Tutte le colonne specificate nel campo facoltativo
Clausola
STORING
(database di dialetti GoogleSQL) oINCLUDE
(database di dialetti PostgreSQL) della definizione dell'indice.
Nel tempo, Spanner analizza le tabelle per garantire che l'istanza secondaria gli indici vengono utilizzati per le query appropriate.
Aggiungi un indice secondario
Il momento più efficiente per aggiungere un indice secondario è quando crei la tabella. Per creare contemporaneamente una tabella e i suoi indici, invia le istruzioni DDL per la nuova tabella e i nuovi indici in una singola richiesta a Spanner.
In Spanner, puoi anche aggiungere un nuovo indice secondario a un mentre il database continua a gestire il traffico. Come per qualsiasi altro schema modifiche in Spanner, l'aggiunta di un indice a un database esistente richiedono la modalità offline del database e non bloccano intere colonne o tabelle.
Ogni volta che viene aggiunto un nuovo indice a una tabella esistente, Spanner Esegue automaticamente il backfill, o compila, l'indice per riflettere una vista aggiornata dei dati indicizzati. Spanner gestisce questo processo di backfill e il processo viene eseguito in background utilizzando le risorse nodo a basso la priorità. Nella maggior parte dei casi non è possibile accelerare il processo (ad es. l'aggiunta di altri nodi) e il backfill non influisce in modo significativo le prestazioni del database.
La creazione degli indici può richiedere da diversi minuti a molte ore. Poiché l'indice la creazione è un aggiornamento dello schema, è vincolata dalle stesse prestazioni vincoli come qualsiasi altro aggiornamento dello schema. L'ora necessari per creare un indice secondario dipende da diversi fattori:
- La dimensione del set di dati
- La capacità di calcolo dell'istanza
- Il carico sull'istanza
Per visualizzare l'avanzamento di un processo di backfill dell'indice, consulta la sezione relativa all'avanzamento.
Tieni presente che, se utilizzi la colonna Timestamp commit come prima, parte dell'indice secondario può creare hotspot e riducono le prestazioni di scrittura.
Utilizza l'istruzione CREATE INDEX
per definire un indice secondario
nel tuo schema. Ecco alcuni esempi:
Per indicizzare tutti i Singers
nel database in base al nome e al cognome:
GoogleSQL
CREATE INDEX SingersByFirstLastName ON Singers(FirstName, LastName);
PostgreSQL
CREATE INDEX SingersByFirstLastName ON Singers(FirstName, LastName);
Per creare un indice di tutti i valori Songs
nel database in base al valore SongName
:
GoogleSQL
CREATE INDEX SongsBySongName ON Songs(SongName);
PostgreSQL
CREATE INDEX SongsBySongName ON Songs(SongName);
Per indicizzare solo i brani di un determinato cantante, utilizza la clausola
INTERLEAVE IN
per interlacciare l'indice nella tabella Singers
:
GoogleSQL
CREATE INDEX SongsBySingerSongName ON Songs(SingerId, SongName),
INTERLEAVE IN Singers;
PostgreSQL
CREATE INDEX SongsBySingerSongName ON Songs(SingerId, SongName)
INTERLEAVE IN Singers;
Per indicizzare solo i brani di un determinato album:
GoogleSQL
CREATE INDEX SongsBySingerAlbumSongName ON Songs(SingerId, AlbumId, SongName),
INTERLEAVE IN Albums;
PostgreSQL
CREATE INDEX SongsBySingerAlbumSongName ON Songs(SingerId, AlbumId, SongName)
INTERLEAVE IN Albums;
Per indicizzare in ordine decrescente di SongName
:
GoogleSQL
CREATE INDEX SongsBySingerAlbumSongNameDesc ON Songs(SingerId, AlbumId, SongName DESC),
INTERLEAVE IN Albums;
PostgreSQL
CREATE INDEX SongsBySingerAlbumSongNameDesc ON Songs(SingerId, AlbumId, SongName DESC)
INTERLEAVE IN Albums;
Tieni presente che l'annotazione DESC
precedente si applica solo a SongName
. Per indicizzare per
in ordine decrescente di altre chiavi indice, aggiungi anche DESC
a queste chiavi:
SingerId DESC, AlbumId DESC
.
Tieni inoltre presente che PRIMARY_KEY
è una parola riservata e non può essere utilizzata come nome
di un indice. È il nome assegnato allo pseudo-index.
quando viene creata una tabella con la specifica PRIMARY KEY
Per ulteriori dettagli e best practice per la scelta di indici senza interleaving e indici con interfoliazione, vedi Opzioni di indice e Utilizzare un indice con interleaving su una colonna il cui valore aumenta o monotonicamente aumenta diminuisce.
Controlla l'avanzamento del backfill dell'indice
Console
Nel menu di navigazione di Spanner, fai clic sulla scheda Operazioni. La La pagina Operazioni mostra un elenco delle operazioni attualmente in esecuzione.
Trova l'operazione di backfill nell'elenco. Se è ancora in esecuzione, indicatore di avanzamento nella colonna Ora di fine che mostra la percentuale completata, come illustrato nell'immagine seguente:
gcloud
Utilizza gcloud spanner operations describe
lo stato di avanzamento di un'operazione.
Recupera l'ID operazione:
gcloud spanner operations list --instance=INSTANCE-NAME \ --database=DATABASE-NAME --type=DATABASE_UPDATE_DDL
Sostituisci quanto segue:
- INSTANCE-NAME con l'istanza Spanner nome.
- DATABASE-NAME con il nome del database.
Note sull'utilizzo:
Per limitare l'elenco, specifica il flag
--filter
. Ad esempio:--filter="metadata.name:example-db"
elenca solo le operazioni su un database specifico.- In
--filter="error:*"
vengono elencate solo le operazioni di backup non riuscite.
Per informazioni sulla sintassi dei filtri, consulta gcloud topic usando i filtri. Per informazioni su come filtrare le operazioni di backup, controlla il campo
filter
in ListBackupOperationsRequest.Il flag
--type
non è sensibile alle maiuscole.
L'output è simile al seguente:
OPERATION_ID STATEMENTS DONE @TYPE _auto_op_123456 CREATE INDEX SingersByFirstLastName ON Singers(FirstName, LastName) False UpdateDatabaseDdlMetadata CREATE INDEX SongsBySingerAlbumSongName ON Songs(SingerId, AlbumId, SongName), INTERLEAVE IN Albums _auto_op_234567 True CreateDatabaseMetadata
Esegui
gcloud spanner operations describe
:gcloud spanner operations describe \ --instance=INSTANCE-NAME \ --database=DATABASE-NAME \ projects/PROJECT-NAME/instances/INSTANCE-NAME/databases/DATABASE-NAME/operations/OPERATION_ID
Sostituisci quanto segue:
- INSTANCE-NAME: il nome dell'istanza Spanner.
- DATABASE-NAME: il nome del database Spanner.
- PROJECT-NAME: il nome del progetto.
- OPERATION-ID: l'ID dell'operazione da eseguire verifica.
La sezione
progress
nell'output mostra la percentuale dell'operazione completato. L'output è simile al seguente:done: true ... progress: - endTime: '2021-01-22T21:58:42.912540Z' progressPercent: 100 startTime: '2021-01-22T21:58:11.053996Z' - progressPercent: 67 startTime: '2021-01-22T21:58:11.053996Z' ...
REST v1
Recupera l'ID operazione:
gcloud spanner operations list --instance=INSTANCE-NAME
--database=DATABASE-NAME --type=DATABASE_UPDATE_DDL
Sostituisci quanto segue:
- INSTANCE-NAME con l'istanza Spanner nome.
- DATABASE-NAME con il nome del database.
Prima di utilizzare i dati della richiesta, effettua le seguenti sostituzioni:
- PROJECT-ID: l'ID progetto.
- INSTANCE-ID: l'ID istanza.
- DATABASE-ID: l'ID del database.
- OPERATION-ID: l'ID operazione.
Metodo HTTP e URL:
GET https://spanner.googleapis.com/v1/projects/PROJECT-ID/instances/INSTANCE-ID/databases/DATABASE-ID/operations/OPERATION-ID
Per inviare la richiesta, espandi una delle seguenti opzioni:
Dovresti ricevere una risposta JSON simile alla seguente:
{ ... "progress": [ { "progressPercent": 100, "startTime": "2023-05-27T00:52:27.366688Z", "endTime": "2023-05-27T00:52:30.184845Z" }, { "progressPercent": 100, "startTime": "2023-05-27T00:52:30.184845Z", "endTime": "2023-05-27T00:52:40.750959Z" } ], ... "done": true, "response": { "@type": "type.googleapis.com/google.protobuf.Empty" } }
Per gcloud
e REST, puoi trovare lo stato di avanzamento di ogni backfill dell'indice
nella sezione progress
. Per ogni istruzione nell'array di istruzioni,
c'è un campo corrispondente nell'array di avanzamento. Questo ordine di avanzamento degli array
corrisponde all'ordine dell'array delle istruzioni. Una volta disponibile,
I campi startTime
, progressPercent
e endTime
vengono compilati di conseguenza.
Tieni presente che l'output non mostra un tempo stimato per il backfill
l'avanzamento del processo sarà completato.
Se l'operazione richiede troppo tempo, puoi annullarla. Per ulteriori informazioni, vedi Annulla creazione indice.
Scenari di visualizzazione dell'avanzamento del backfill dell'indice
Esistono diversi scenari che si possono verificare quando si cerca di controllare avanzamento di un backfill dell'indice. Istruzioni per la creazione di indici che richiedono un indice il backfill fa parte delle operazioni di aggiornamento dello schema e possono essere istruzioni che fanno parte di un'operazione di aggiornamento dello schema.
Il primo scenario è il più semplice, ovvero quando l'istruzione di creazione dell'indice è la prima nell'operazione di aggiornamento dello schema. Dalla creazione dell'indice
è la prima istruzione, è la prima elaborata ed eseguita
ordine di esecuzione.
Immediatamente, il campo startTime
dell'istruzione di creazione dell'indice
viene compilata con l'ora di inizio dell'operazione di aggiornamento dello schema. Poi, l'indice
il campo progressPercent
dell'istruzione di creazione viene compilato quando l'avanzamento di
il backfill dell'indice è superiore allo 0%. Infine, il campo endTime
viene compilato una volta
la dichiarazione viene confermata.
Il secondo scenario è quando l'istruzione di creazione dell'indice non è la prima
nell'operazione di aggiornamento dello schema. Nessun campo correlato all'indice
l'istruzione di creazione si compilerà fino a quando le istruzioni precedenti
a causa
ordine di esecuzione.
Analogamente allo scenario precedente, una volta confermate le dichiarazioni precedenti,
Il campo startTime
dell'istruzione di creazione dell'indice viene compilato per primo, seguito da
nel campo progressPercent
. Infine, il campo endTime
viene compilato al termine del commit dell'istruzione.
Annulla creazione indice
Puoi utilizzare Google Cloud CLI per annullare la creazione dell'indice. Per recuperare un elenco di
le operazioni schema-update per un database Spanner, utilizza
gcloud spanner operations list
e includi
l'opzione --filter
:
gcloud spanner operations list \
--instance=INSTANCE \
--database=DATABASE \
--filter="@TYPE:UpdateDatabaseDdlMetadata"
Trova il OPERATION_ID
per l'operazione da annullare, quindi utilizza il metodo
Comando gcloud spanner operations cancel
per annullare
Questo:
gcloud spanner operations cancel OPERATION_ID \
--instance=INSTANCE \
--database=DATABASE
Visualizza indici esistenti
Per visualizzare le informazioni sugli indici esistenti in un database, puoi utilizzare il comando Console Google Cloud o Google Cloud CLI:
Console
Vai alla pagina Istanze di Spanner nella console Google Cloud.
Fai clic sul nome dell'istanza che vuoi visualizzare.
Nel riquadro a sinistra, fai clic sul database da visualizzare, quindi fai clic sulla che vuoi visualizzare.
Fai clic sulla scheda Indici. La console Google Cloud mostra un elenco di indici.
(Facoltativo) Per visualizzare i dettagli di un indice, ad esempio le colonne include, fai clic sul nome dell'indice.
gcloud
Utilizza il comando gcloud spanner databases ddl describe
:
gcloud spanner databases ddl describe DATABASE \
--instance=INSTANCE
L'gcloud CLI stampa il DDL (Data Definition Language)
per creare le tabelle e gli indici del database. Le istruzioni CREATE
INDEX
descrivono gli indici esistenti. Per
esempio:
--- |-
CREATE TABLE Singers (
SingerId INT64 NOT NULL,
FirstName STRING(1024),
LastName STRING(1024),
SingerInfo BYTES(MAX),
) PRIMARY KEY(SingerId)
---
CREATE INDEX SingersByFirstLastName ON Singers(FirstName, LastName)
Eseguire query con un indice specifico
Le sezioni seguenti spiegano come specificare un indice in un'istruzione SQL e
con l'interfaccia di lettura per Spanner. Gli esempi in queste sezioni
supponiamo di aver aggiunto una colonna MarketingBudget
alla tabella Albums
e
ha creato un indice denominato AlbumsByAlbumTitle
:
GoogleSQL
CREATE TABLE Albums (
SingerId INT64 NOT NULL,
AlbumId INT64 NOT NULL,
AlbumTitle STRING(MAX),
MarketingBudget INT64,
) PRIMARY KEY (SingerId, AlbumId),
INTERLEAVE IN PARENT Singers ON DELETE CASCADE;
CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle);
PostgreSQL
CREATE TABLE Albums (
SingerId BIGINT NOT NULL,
AlbumId BIGINT NOT NULL,
AlbumTitle VARCHAR,
MarketingBudget BIGINT,
PRIMARY KEY (SingerId, AlbumId)
) INTERLEAVE IN PARENT Singers ON DELETE CASCADE;
CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle);
Specifica un indice in un'istruzione SQL
Quando usi SQL per eseguire query su una tabella Spanner, Spanner automaticamente
utilizza tutti gli indici che potrebbero rendere la query più efficiente. Di conseguenza,
Non devi specificare un indice
per le query SQL. Tuttavia,
per le query fondamentali per il tuo carico di lavoro, Google ti consiglia di usare
FORCE_INDEX
nelle istruzioni SQL per prestazioni più coerenti.
In alcuni casi, Spanner potrebbe scegliere un indice che aumenti la latenza delle query. Se hai seguito i passaggi per la risoluzione dei problemi relativi alle regressioni del rendimento e hai confermato che è opportuno provare un altro indice per la query, puoi specificarlo all'interno della query.
Per specificare un indice in un'istruzione SQL, utilizza l'opzione FORCE_INDEX
per fornire un'istruzione di indice. Le istruzioni di indice utilizzano la seguente sintassi:
GoogleSQL
FROM MyTable@{FORCE_INDEX=MyTableIndex}
PostgreSQL
FROM MyTable /*@ FORCE_INDEX = MyTableIndex */
Puoi anche utilizzare una istruzione di indice per indicare a Spanner di eseguire la scansione della base anziché utilizzare un indice:
GoogleSQL
FROM MyTable@{FORCE_INDEX=_BASE_TABLE}
PostgreSQL
FROM MyTable /*@ FORCE_INDEX = _BASE_TABLE */
L'esempio seguente mostra una query SQL che specifica un indice:
GoogleSQL
SELECT AlbumId, AlbumTitle, MarketingBudget
FROM Albums@{FORCE_INDEX=AlbumsByAlbumTitle}
WHERE AlbumTitle >= "Aardvark" AND AlbumTitle < "Goo";
PostgreSQL
SELECT AlbumId, AlbumTitle, MarketingBudget
FROM Albums /*@ FORCE_INDEX = AlbumsByAlbumTitle */
WHERE AlbumTitle >= 'Aardvark' AND AlbumTitle < 'Goo';
Un'istruzione di indice potrebbe forzare il processore di query di Spanner a leggere
colonne aggiuntive richieste dalla query, ma non archiviate nell'indice.
Il processore di query recupera queste colonne unendo l'indice e la base
tabella. Per evitare questo join aggiuntivo, utilizza un
STORING
(database di dialetti GoogleSQL) o INCLUDE
(database di dialetti PostgreSQL) per
archiviare le colonne aggiuntive nell'indice.
Nell'esempio precedente, la colonna MarketingBudget
non è
archiviati nell'indice, ma la query SQL seleziona questa colonna. Di conseguenza,
Spanner deve cercare la colonna MarketingBudget
nella tabella di base,
e uniscilo ai dati dell'indice per restituire i risultati della query.
Spanner genera un errore se l'istruzione di indice include uno dei seguenti elementi problemi:
- L'indice non esiste.
- L'indice si trova su un'altra tabella di base.
- Nella query manca un filtro
NULL
obbligatorio per un indiceNULL_FILTERED
.
I seguenti esempi mostrano come scrivere ed eseguire query che recuperano i valori
valori di AlbumId
, AlbumTitle
e MarketingBudget
utilizzando l'indice
AlbumsByAlbumTitle
:
C++
C#
Vai
Java
Node.js
PHP
Python
Ruby
Specifica un indice nell'interfaccia di lettura
Quando usi l'interfaccia di lettura per Spanner e vuoi che Spanner per utilizzare un indice, devi specificarlo. L'interfaccia di lettura non seleziona automaticamente l'indice.
Inoltre, l'indice deve contenere tutti i dati visualizzati nella query di risultati, escluse le colonne che fanno parte della chiave primaria. Questa limitazione esiste perché l'interfaccia di lettura non supporta le unioni tra l'indice e la tabella di base. Se devi includere altre colonne nei risultati della query, hai alcune opzioni:
- Utilizza una clausola
STORING
oINCLUDE
per archiviare le colonne aggiuntive in dell'indice. - Esegui la query senza includere le colonne aggiuntive, poi utilizza le chiavi primarie per invia un'altra query che legga le colonne aggiuntive.
Spanner restituisce i valori dell'indice in ordine crescente in base alla chiave dell'indice. Per recuperare i valori in ordine decrescente:
Annota la chiave indice con
DESC
. Ad esempio:CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle DESC);
L'annotazione
DESC
si applica a una singola chiave di indice. Se l'indice include chiave e i risultati della query devono essere visualizzati in in base a tutte le chiavi, includi un'annotazioneDESC
per ogni chiave.Se la lettura specifica un intervallo di chiavi, assicurati che sia anche in ordine decrescente. In altre parole, il valore della chiave iniziale deve essere maggiore del valore della chiave finale.
L'esempio seguente mostra come recuperare i valori di AlbumId
e
AlbumTitle
con l'indice AlbumsByAlbumTitle
:
C++
C#
Vai
Java
Node.js
PHP
Python
Ruby
Creare un indice per le scansioni solo dell'indice
Facoltativamente, puoi utilizzare la clausola STORING
(per i database di dialetti GoogleSQL) o INCLUDE
(per i database di dialetti PostgreSQL) per archiviare una copia di una colonna nella
indice. Questo tipo di indice offre vantaggi per le query e le chiamate di lettura utilizzando
l'indice, al costo dell'utilizzo di spazio di archiviazione aggiuntivo:
- Le query SQL che utilizzano l'indice e selezionano le colonne memorizzate nella clausola
STORING
oINCLUDE
non richiedono un'unione aggiuntiva alla tabella di base. - Le chiamate
read()
che utilizzano l'indice possono leggere le colonne memorizzate dalla clausolaSTORING
/INCLUDE
.
Ad esempio, supponi di aver creato una versione alternativa di AlbumsByAlbumTitle
che archivia una copia della colonna MarketingBudget
nell'indice (nota
Clausola STORING
o INCLUDE
in grassetto):
GoogleSQL
CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) STORING (MarketingBudget);
PostgreSQL
CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) INCLUDE (MarketingBudget);
Con l'indice AlbumsByAlbumTitle
precedente, Spanner deve unirsi all'indice
con la tabella di base, quindi recupera la colonna dalla tabella di base. Con le nuove
AlbumsByAlbumTitle2
, Spanner legge la colonna direttamente dalla
che è più efficiente.
Se utilizzi l'interfaccia di lettura anziché SQL, il nuovo AlbumsByAlbumTitle2
consente anche di leggere direttamente la colonna MarketingBudget
:
C++
C#
Vai
Java
Node.js
PHP
Python
Ruby
Modificare un indice
Puoi utilizzare l'istruzione ALTER INDEX
per aggiungere altre colonne
in un indice esistente o eliminare colonne. Questo
può aggiornare l'elenco di colonne definito dalla clausola STORING
(database di dialetti GoogleSQL) o la clausola INCLUDE
(database di dialetti PostgreSQL) quando crei
indice. Non puoi utilizzare questa istruzione per aggiungere o rimuovere colonne
colonne dalla chiave di indice. Ad esempio, invece di creare una nuova
indice AlbumsByAlbumTitle2
, puoi usare ALTER INDEX
per aggiungere un
in AlbumsByAlbumTitle
, come mostrato nell'esempio seguente:
GoogleSQL
ALTER INDEX AlbumsByAlbumTitle ADD STORED COLUMN MarketingBudget
PostgreSQL
ALTER INDEX AlbumsByAlbumTitle ADD INCLUDE COLUMN MarketingBudget
Quando aggiungi una nuova colonna a un indice esistente, Spanner
utilizza un processo di backfill in background. Durante il backfill,
la colonna dell'indice non è leggibile, quindi potresti non ottenere
un miglioramento delle prestazioni. Puoi utilizzare il comando gcloud spanner operations
per elencare l'operazione a lunga esecuzione e visualizzarne lo stato.
Per ulteriori informazioni, consulta la sezione Descrivere l'operazione.
Puoi anche utilizzare l'opzione Annulla operazione per annullare un'operazione in esecuzione.
Al termine del backfill, Spanner aggiunge la colonna all'indice. Come indice diventa più grande, questo potrebbe rallentare le query che utilizzano l'indice.
L'esempio seguente mostra come eliminare una colonna da un indice:
GoogleSQL
ALTER INDEX AlbumsByAlbumTitle DROP STORED COLUMN MarketingBudget
PostgreSQL
ALTER INDEX AlbumsByAlbumTitle DROP INCLUDE COLUMN MarketingBudget
Indice dei valori NULL
Per impostazione predefinita, Spanner indicizza i valori NULL
. Ad esempio, ricorda la
definizione dell'indice SingersByFirstLastName
nella tabella Singers
:
CREATE INDEX SingersByFirstLastName ON Singers(FirstName, LastName);
Tutte le righe di Singers
vengono indicizzate anche se FirstName
o LastName
, oppure
entrambi sono NULL
.
Quando i valori NULL
vengono indicizzati, puoi eseguire query e letture SQL efficienti
sui dati che includono valori NULL
. Ad esempio, utilizza questa istruzione
di query SQL
per trovare tutti i Singers
con un NULL
FirstName
:
GoogleSQL
SELECT s.SingerId, s.FirstName, s.LastName
FROM Singers@{FORCE_INDEX=SingersByFirstLastName} AS s
WHERE s.FirstName IS NULL;
PostgreSQL
SELECT s.SingerId, s.FirstName, s.LastName
FROM Singers /* @ FORCE_INDEX = SingersByFirstLastName */ AS s
WHERE s.FirstName IS NULL;
Ordinamento per i valori NULL
Spanner ordina NULL
come il valore più piccolo per qualsiasi tipo specifico. Per un
colonna in ordine crescente (ASC
), i valori NULL
vengono ordinati per primi. Per una colonna in
in ordine decrescente (DESC
), NULL
valori vengono ordinati per ultimi.
Disattiva l'indicizzazione dei valori NULL
GoogleSQL
Per disabilitare l'indicizzazione dei valori null, aggiungi la parola chiave NULL_FILTERED
all'indice
definizione di Kubernetes. Gli indici NULL_FILTERED
sono particolarmente utili per l'indicizzazione di dati sparsi
in cui la maggior parte delle righe contiene un valore NULL
. In questi casi,
L'indice NULL_FILTERED
può essere notevolmente più piccolo e più efficiente da mantenere
rispetto a un indice normale che include valori di NULL
.
Ecco una definizione alternativa di SingersByFirstLastName
che corrisponde
non indicizza i valori NULL
:
CREATE NULL_FILTERED INDEX SingersByFirstLastNameNoNulls
ON Singers(FirstName, LastName);
La parola chiave NULL_FILTERED
si applica a tutte le colonne chiave dell'indice. Non puoi specificare
NULL
in base alle singole colonne.
PostgreSQL
Per filtrare le righe con valori nulli in una o più colonne indicizzate, utilizza il metodo
Predicato WHERE COLUMN IS NOT NULL
.
Gli indici filtrati per valori null sono particolarmente utili per indicizzare le colonne sparse, in cui la maggior parte delle righe contiene un valore NULL
. In questi casi,
l'indice con filtri nulli può essere notevolmente più piccolo e più efficiente da mantenere
rispetto a un indice normale che include valori NULL
.
Ecco una definizione alternativa di SingersByFirstLastName
che corrisponde
non indicizza i valori NULL
:
CREATE INDEX SingersByFirstLastNameNoNulls
ON Singers(FirstName, LastName)
WHERE FirstName IS NOT NULL
AND LastName IS NOT NULL;
L'esclusione dei valori NULL
impedisce a Spanner di utilizzarli per alcune query. Ad esempio, Spanner non usa l'indice per questa query,
perché l'indice omette eventuali righe Singers
per le quali LastName
è NULL
; come
come risultato, l'utilizzo dell'indice impedisce alla query di restituire le righe corrette:
GoogleSQL
FROM Singers@{FORCE_INDEX=SingersByFirstLastNameNoNulls}
WHERE FirstName = "John";
PostgreSQL
FROM Singers /*@ FORCE_INDEX = SingersByFirstLastNameNoNulls */
WHERE FirstName = 'John';
Per abilitare Spanner all'uso dell'indice, devi riscrivere la query in modo che esclude le righe escluse anche dall'indice:
GoogleSQL
SELECT FirstName, LastName
FROM Singers@{FORCE_INDEX=SingersByFirstLastNameNoNulls}
WHERE FirstName = 'John' AND LastName IS NOT NULL;
PostgreSQL
SELECT FirstName, LastName
FROM Singers /*@ FORCE_INDEX = SingersByFirstLastNameNoNulls */
WHERE FirstName = 'John' AND LastName IS NOT NULL;
Campi proto dell'indice
Utilizza le colonne generate per indicizzare i campi nei buffer di protocollo memorizzati nelle colonne PROTO
, a condizione che i campi sottoposti a indicizzazione utilizzino i tipi di dati primitivi o ENUM
.
Se definisci un indice nel campo di un messaggio di protocollo, non puoi modificare o rimuovere questo campo dallo schema proto. Per ulteriori informazioni, vedi Aggiornamenti agli schemi che contengono un indice sui campi protocollo.
Di seguito è riportato un esempio della tabella Singers
con un protocollo SingerInfo
. Per definire un indice sul campo nationality
di PROTO
,
devi creare una colonna generata archiviata:
GoogleSQL
CREATE PROTO BUNDLE (googlesql.example.SingerInfo, googlesql.example.SingerInfo.Residence);
CREATE TABLE Singers (
SingerId INT64 NOT NULL,
...
SingerInfo googlesql.example.SingerInfo,
SingerNationality STRING(MAX) AS (SingerInfo.nationality) STORED
) PRIMARY KEY (SingerId);
Ha la seguente definizione del tipo di proto googlesql.example.SingerInfo
:
GoogleSQL
package googlesql.example;
message SingerInfo {
optional string nationality = 1;
repeated Residence residence = 2;
message Residence {
required int64 start_year = 1;
optional int64 end_year = 2;
optional string city = 3;
optional string country = 4;
}
}
Quindi definisci un indice sul campo nationality
del proto:
GoogleSQL
CREATE INDEX SingersByNationality ON Singers(SingerNationality);
La seguente query SQL legge i dati utilizzando l'indice precedente:
GoogleSQL
SELECT s.SingerId, s.FirstName
FROM Singers AS s
WHERE s.SingerNationality = "English";
Note:
- Utilizza un'istruzione di indice per accedere agli indici in delle colonne del buffer di protocollo.
- Non puoi creare un indice su campi ripetuti del buffer di protocollo.
Aggiornamenti agli schemi che contengono un indice sui campi proto
Se definisci un indice in un campo del messaggio di protocollo, non puoi modificare o rimuovere quel campo dallo schema proto. Questo perché dopo aver definito l'indice, viene eseguito ogni volta che lo schema viene aggiornato. Spanner acquisisce le informazioni sul tipo per tutti i campi nel percorso che vengono utilizzati nella definizione dell'indice.
Indici univoci
Gli indici possono essere dichiarati UNIQUE
. Gli indici UNIQUE
aggiungono un vincolo al
dati indicizzati che impediscono voci duplicate per una determinata chiave di indice.
Questo vincolo viene applicato da Spanner al momento del commit della transazione.
Nello specifico, non verrà eseguito il commit di qualsiasi transazione che causerebbe l'esistenza di più voci dell'indice per la stessa chiave.
Se una tabella contiene dati non UNIQUE
al suo interno, il tentativo di
la creazione di un indice UNIQUE
non riuscirà.
Una nota sugli indici UNIQUE NULL_FILTERED
Un indice UNIQUE NULL_FILTERED
non applica l'univocità della chiave di indice quando:
almeno una delle parti principali dell'indice è NULL.
Ad esempio, supponiamo di aver creato la tabella e l'indice seguenti:
GoogleSQL
CREATE TABLE ExampleTable (
Key1 INT64 NOT NULL,
Key2 INT64,
Key3 INT64,
Col1 INT64,
) PRIMARY KEY (Key1, Key2, Key3);
CREATE UNIQUE NULL_FILTERED INDEX ExampleIndex ON ExampleTable (Key1, Key2, Col1);
PostgreSQL
CREATE TABLE ExampleTable (
Key1 BIGINT NOT NULL,
Key2 BIGINT,
Key3 BIGINT,
Col1 BIGINT,
PRIMARY KEY (Key1, Key2, Key3)
);
CREATE UNIQUE INDEX ExampleIndex ON ExampleTable (Key1, Key2, Col1)
WHERE Key1 IS NOT NULL
AND Key2 IS NOT NULL
AND Col1 IS NOT NULL;
Le due righe seguenti in ExampleTable
hanno gli stessi valori per l'elemento secondario
chiavi indice Key1
, Key2
e Col1
:
1, NULL, 1, 1
1, NULL, 2, 1
Poiché Key2
è NULL
e l'indice è con filtri null, le righe non saranno
presente nell'indice ExampleIndex
. Poiché non vengono inseriti nell'indice, l'indice non li rifiuterà per violazione dell'unicità su (Key1, Key2,
Col1)
.
Se vuoi che l'indice imponga l'unicità dei valori della tupla (Key1
,
Key2
, Col1
), devi annotare Key2
con NOT NULL
nella definizione della tabella o creare l'indice senza filtrare i valori null.
Rilascia un indice
Utilizza l'istruzione DROP INDEX
per rimuovere un indice secondario da
lo schema.
Per rilasciare l'indice denominato SingersByFirstLastName
:
DROP INDEX SingersByFirstLastName;
Indice per una scansione più rapida
Quando Spanner deve eseguire una scansione della tabella (anziché una scansione indicizzata lookup) per recuperare i valori da una o più colonne, puoi ricevere risultati se esiste un indice per quelle colonne, e nell'ordine specificato dalla query. Se esegui spesso che richiedono scansioni, valuta la possibilità di creare indici secondari per queste scansioni vengono eseguite in modo più efficiente.
In particolare, se hai bisogno di Spanner per analizzare frequentemente chiave primaria o un altro indice in ordine inverso, puoi aumentarne efficienza attraverso un indice secondario che rende l’ordine scelto esplicito.
Ad esempio, la seguente query restituisce sempre un risultato rapido, anche se
Spanner deve analizzare Songs
per trovare il valore più basso di
SongId
:
SELECT SongId FROM Songs LIMIT 1;
SongId
è la chiave primaria della tabella, archiviata (come in tutte le chiavi primarie)
in ordine crescente. Spanner può scansionare l'indice di quella chiave e trovare
rapidamente il primo risultato.
Tuttavia, senza l'aiuto di un indice secondario, la seguente query non
tornare rapidamente, soprattutto se Songs
contiene molti dati:
SELECT SongId FROM Songs ORDER BY SongId DESC LIMIT 1;
Anche se SongId
è la chiave primaria della tabella, Spanner non ha
per recuperare il valore più alto della colonna senza dover ricorrere a un
scansione della tabella.
L'aggiunta del seguente indice consentirebbe a questa query di restituire più dati rapidamente:
CREATE INDEX SongIdDesc On Songs(SongId DESC);
Con questo indice attivo, Spanner lo userebbe per restituire una per la seconda query molto più rapidamente.
Passaggi successivi
- Scopri le best practice SQL per Spanner.
- Scopri di più sui piani di esecuzione delle query per Spanner.
- Scopri come risolvere i problemi di regressione delle prestazioni in SQL query.