Questa pagina descrive come eseguire letture in Spanner al di fuori del contesto delle transazioni di sola lettura e lettura/scrittura. Se si verifica una delle seguenti condizioni, devi leggere la pagina Transazioni:
Se hai bisogno di scrivere, a seconda del valore di una o più letture, devi eseguire la lettura come parte di una transazione di lettura-scrittura. Per ulteriori informazioni, consulta la sezione sulle transazioni di lettura/scrittura.
Se effettui più chiamate di lettura che richiedono una visualizzazione coerente dei tuoi dati, devi eseguirle come parte di una transazione di sola lettura. Per maggiori informazioni, vedi Transazioni di sola lettura.
Tipi di lettura
Spanner consente di determinare il livello di attualità dei dati quando leggi i dati offrendo due tipi di letture:
- Una lettura forte è una lettura in un timestamp corrente e garantisce la visualizzazione di tutti i dati il cui commit fino all'inizio di questa lettura. Spanner utilizza per impostazione predefinita l'utilizzo di letture efficaci per gestire le richieste di lettura.
- Una lettura inattiva viene letta in un timestamp nel passato. Se la tua applicazione è sensibile alla latenza, ma tollera i dati inattivi, le letture inattive possono offrire vantaggi in termini di prestazioni.
Per scegliere il tipo di lettura desiderato, imposta un timestamp bound nella richiesta di lettura. Per la scelta di un timestamp associato, segui queste best practice:
Scegli letture efficaci quando possibile. Questi sono i timestamp predefiniti associati alle letture di Spanner, incluse le transazioni di sola lettura. È garantito che le letture elevate osservino gli effetti di tutte le transazioni eseguite prima dell'inizio dell'operazione, indipendentemente dalla replica che riceve la lettura. Per questo motivo, le letture efficaci rendono il codice dell'applicazione più semplice e le applicazioni più affidabili. Scopri di più sulle proprietà di coerenza di Spanner in TrueTime e coerenza esterna.
Se la latenza rende inattuabili letture efficaci in alcune situazioni, utilizza le letture obsolete (inattività limitata o inattive) per migliorare le prestazioni nelle posizioni in cui non è necessario che le letture siano il più recenti possibile. Come descritto nella pagina Replica, 15 secondi è un valore di inattività ragionevole da utilizzare per ottenere buone prestazioni.
Leggere i dati con un ruolo di database
Se sei un utente con controllo dell'accesso granulare, devi selezionare un ruolo di database per eseguire query e istruzioni SQL ed eseguire operazioni sulle righe su un database. La selezione del ruolo persiste per tutta la sessione finché non lo cambi.
Per istruzioni su come eseguire una lettura con un ruolo di database, vedi Accedere a un database con controllo dell'accesso granulare.
Metodi di lettura singoli
Spanner supporta metodi di lettura singoli (ovvero una lettura al di fuori del contesto di una transazione) su un database per:
- Esecuzione della lettura come istruzione di query SQL o utilizzando l'API di lettura di Spanner.
- Esecuzione di una lettura efficace da una singola riga o più righe di una tabella.
- Esecuzione di una lettura inattiva da una singola riga o da più righe di una tabella.
- Lettura da una singola riga o da più righe in un indice secondario.
Se vuoi instradare singole letture a una replica o a una regione specifica all'interno di una configurazione di istanze multiregionali o di una configurazione regionale personalizzata con regioni facoltative di sola lettura, consulta Letture dirette.
Le seguenti sezioni descrivono come utilizzare i metodi di lettura con le librerie client di Spanner.
Esegui una query
Di seguito viene illustrato come eseguire un'istruzione di query SQL su un database.
GoogleSQL
C++
Usa ExecuteQuery()
per eseguire un'istruzione di query SQL su un database.
C#
Usa ExecuteReaderAsync()
per eseguire query sul database.
Go
Usa Client.Single().Query
per eseguire query sul database.
Java
Usa ReadContext.executeQuery
per eseguire query sul database.
Node.js
Usa Database.run
per eseguire query sul database.
PHP
Usa Database::execute
per eseguire query sul database.
Python
Usa Database.execute_sql
per eseguire query sul database.
Ruby
Usa Client#execute
per eseguire query sul database.
Consulta i riferimenti alla sintassi delle query e alle funzioni e operatori di SQL quando crei un'istruzione SQL.
Esegui una lettura efficace
Di seguito viene illustrato come eseguire una lettura sicura di zero o più righe da un database.
GoogleSQL
C++
Il codice per leggere i dati è uguale all'esempio precedente per eseguire query su Spanner eseguendo una query SQL.
C#
Il codice per leggere i dati è uguale all'esempio precedente per eseguire query su Spanner eseguendo una query SQL.
Go
Utilizza Client.Single().Read
per leggere le righe del database.
L'esempio utilizza AllKeys
per definire una raccolta di chiavi o intervalli di chiavi da leggere.
Java
Utilizza ReadContext.read
per leggere le righe del database.
L'esempio utilizza KeySet
per definire una raccolta di chiavi o intervalli di chiavi da leggere.
Node.js
Utilizza Table.read
per leggere le righe del database.
L'esempio utilizza keySet
per definire una raccolta di chiavi o intervalli di chiavi da leggere.
PHP
Utilizza Database::read
per leggere le righe del database.
L'esempio utilizza keySet
per definire una raccolta di chiavi o intervalli di chiavi da leggere.
Python
Utilizza Database.read
per leggere le righe del database.
L'esempio utilizza KeySet
per definire una raccolta di chiavi o intervalli di chiavi da leggere.
Ruby
Utilizza Client#read
per leggere le righe del database.
Esegui una lettura inattiva
Il codice campione riportato di seguito mostra come eseguire una lettura inattiva di zero o più righe da un database utilizzando un vincolo di timestamp exact-staleness. Per istruzioni su come eseguire una lettura inattiva utilizzando un timestamp associato a un timestamp bounded-staleness, vedi la nota dopo il codice campione. Per ulteriori informazioni sui diversi tipi di limiti disponibili, consulta la sezione Limiti di timestamp.
GoogleSQL
C++
Utilizza ExecuteQuery()
con MakeReadOnlyTransaction()
e
Transaction::ReadOnlyOptions()
per eseguire una lettura inattiva.
C#
Usa il metodo BeginReadOnlyTransactionAsync
su un connection
con un
valore TimestampBound.OfExactStaleness()
specificato per eseguire query sul database.
Go
Utilizza Client.ReadOnlyTransaction().WithTimestampBound()
e specifica un valore ExactStaleness
per eseguire una lettura di righe dal database utilizzando un timestamp di inattività esatta.
L'esempio utilizza AllKeys
per definire una raccolta di chiavi o intervalli di chiavi da leggere.
Java
Utilizza il metodo read
di un ReadContext
con un valore TimestampBound.ofExactStaleness()
specificato per eseguire una lettura di righe dal database utilizzando un timestamp di inattività esatta.
L'esempio utilizza KeySet
per definire una raccolta di chiavi o intervalli di chiavi da leggere.
Node.js
Utilizza Table.read
con l'opzione exactStaleness
per eseguire una lettura delle righe
dal database utilizzando un vincolo di timestamp di inattività esatta.
L'esempio utilizza keySet
per definire una raccolta di chiavi o intervalli di chiavi da leggere.
PHP
Utilizza Database::read
con un valore exactStaleness
specificato per eseguire una lettura di righe dal database utilizzando un vincolo di timestamp di inattività esatta.
L'esempio utilizza keySet
per definire una raccolta di chiavi o intervalli di chiavi da leggere.
Python
Utilizza il metodo read
di un Database
snapshot
che ha un valore exact_staleness
specificato per eseguire una lettura di righe dal database utilizzando un timestamp di inattività esatta.
L'esempio utilizza KeySet
per definire una raccolta di chiavi o intervalli di chiavi da leggere.
Ruby
Utilizza il metodo read
di uno snapshot Client
che ha un valore staleness
specificato (in secondi) per eseguire una lettura di righe dal database utilizzando un timestamp di inattività esatta.
Esegui una lettura utilizzando un indice
Di seguito viene illustrato come leggere zero o più righe da un database utilizzando un indice:
GoogleSQL
C++
Utilizza la funzione Read()
per eseguire una lettura utilizzando un indice.
C#
Leggi i dati utilizzando l'indice eseguendo una query che specifica esplicitamente l'indice:
Go
Utilizza Client.Single().ReadUsingIndex
per leggere le righe del database utilizzando un indice.
Java
Utilizza ReadContext.readUsingIndex
per leggere le righe del database utilizzando un indice.
Node.js
Utilizza Table.read
e specifica l'indice nella query per leggere le righe del database utilizzando un indice.
PHP
Utilizza Database::read
e specifica l'indice per leggere le righe del database
utilizzando un indice.
Python
Utilizza Database.read
e specifica l'indice per leggere le righe del database
utilizzando un indice.
Ruby
Utilizza Client#read
e specifica l'indice per leggere le righe del database utilizzando un indice.
Lettura di dati in parallelo
Quando esegui operazioni di lettura o query in blocco che coinvolgono grandi quantità di dati da Spanner, puoi utilizzare l'API PartitionQuery
per risultati più rapidi. L'API divide la query in batch, o
partizioni, utilizzando più macchine per recuperare le partizioni in parallelo. Tieni presente che l'utilizzo dell'API PartitionQuery
causa una latenza più elevata perché è destinata solo a operazioni collettive come l'esportazione o la scansione dell'intero database.
Puoi eseguire qualsiasi operazione di lettura dell'API in parallelo utilizzando le librerie client di Spanner. Tuttavia, puoi eseguire il partizionamento delle query SQL solo quando le query sono partizionabili in base alla radice. Affinché una query sia partizionabile dalla directory principale, il piano di query deve soddisfare una delle seguenti condizioni:
Il primo operatore nel piano di esecuzione delle query è un unione distribuita e quest'ultimo contiene solo un unione distribuita (escluse le unioni di distribuzione locali). Il piano di query non può contenere altri operatori distribuiti, come Cross apply.
Non esistono operatori distribuiti nel piano di query.
L'API PartitionQuery
esegue le query in modalità batch. Spanner potrebbe scegliere un piano di esecuzione delle query che renda le query partizionabili a livello radice quando vengono eseguite in modalità batch. Di conseguenza, l'API PartitionQuery
e Spanner Studio potrebbero utilizzare piani di esecuzione delle query diversi per la stessa query. Potresti non riuscire a ottenere il piano di esecuzione della query utilizzato dall'API PartitionQuery
su Spanner Studio.
Per query partizionate come questa, puoi scegliere di abilitare Spanner Data Boost. Data Boost consente di eseguire query analitiche di grandi dimensioni con un impatto prossimo allo zero sui carichi di lavoro esistenti sull'istanza Spanner di cui è stato eseguito il provisioning. Gli esempi di codice C++, Go, Java, Node.js e Python in questa pagina mostrano come abilitare Data Boost.
Per ulteriori informazioni su Data Boost, consulta Panoramica di Data Boost.
GoogleSQL
C++
Questo esempio recupera le partizioni di una query SQL della tabella Singers
ed esegue la query su ogni partizione tramite i seguenti passaggi:
- Creazione di una transazione batch di Spanner.
- Generare partizioni per la query, in modo che possano essere distribuite a più worker.
- Recupero dei risultati della query per ogni partizione.
C#
Questo esempio recupera le partizioni di una query SQL della tabella Singers
ed esegue la query su ogni partizione tramite i seguenti passaggi:
- Creazione di una transazione batch di Spanner.
- Generare partizioni per la query, in modo che possano essere distribuite a più worker.
- Recupero dei risultati della query per ogni partizione.
Go
Questo esempio recupera le partizioni di una query SQL della tabella Singers
ed esegue la query su ogni partizione tramite i seguenti passaggi:
- Creazione di un client Spanner e di una transazione.
- Generare partizioni per la query, in modo che possano essere distribuite a più worker.
- Recupero dei risultati della query per ogni partizione.
Java
Questo esempio recupera le partizioni di una query SQL della tabella Singers
ed esegue la query su ogni partizione tramite i seguenti passaggi:
- Creazione di un client batch di Spanner e di una transazione.
- Generare partizioni per la query, in modo che possano essere distribuite a più worker.
- Recupero dei risultati della query per ogni partizione.
Node.js
Questo esempio recupera le partizioni di una query SQL della tabella Singers
ed esegue la query su ogni partizione tramite i seguenti passaggi:
- Creazione di un client Spanner e di un batch.
- Generare partizioni per la query, in modo che possano essere distribuite a più worker.
- Recupero dei risultati della query per ogni partizione.
PHP
Questo esempio recupera le partizioni di una query SQL della tabella Singers
ed esegue la query su ogni partizione tramite i seguenti passaggi:
- Creazione di un client Spanner e di un batch.
- Generare partizioni per la query, in modo che possano essere distribuite a più worker.
- Recupero dei risultati della query per ogni partizione.
Python
Questo esempio recupera le partizioni di una query SQL della tabella Singers
ed esegue la query su ogni partizione tramite i seguenti passaggi:
- Creazione di un client Spanner e di una transazione batch.
- Generare partizioni per la query, in modo che possano essere distribuite a più worker.
- Recupero dei risultati della query per ogni partizione.
Ruby
Questo esempio recupera le partizioni di una query SQL della tabella Singers
ed esegue la query su ogni partizione tramite i seguenti passaggi:
- Creazione di un client batch di Spanner.
- Creare partizioni per la query, in modo che possano essere distribuite a più worker.
- Recupero dei risultati della query per ogni partizione.