Cette page décrit comment effectuer des lectures dans Spanner en dehors du contexte des transactions en lecture seule et en lecture/écriture. Si l'un des cas suivants s'applique, vous devriez plutôt lire la page Transactions:
Si vous avez besoin d'effectuer une écriture, en fonction de la valeur d'une ou plusieurs lectures, vous devez exécuter la lecture dans le cadre d'une transaction en lecture-écriture. Pour en savoir plus, consultez la section Transactions en lecture-écriture.
Si vous effectuez plusieurs appels en lecture nécessitant une vue cohérente de vos données, vous devez exécuter les lectures dans le cadre d'une transaction en lecture seule. Pour en savoir plus, consultez la section Transactions en lecture seule.
Types de lecture
Spanner vous permet de déterminer le niveau d'actualisation des données lorsque vous les lisez en proposant deux types de lectures:
- La lecture forte qui est une lecture avec un horodatage actuel. Elle garantit l'affichage de toutes les données qui ont été enregistrées jusqu'au début de cette lecture. Spanner se sert par défaut des lectures fortes pour répondre aux requêtes de lecture.
- La lecture non actualisée qui est une lecture avec un horodatage passé. Si votre application est sensible au temps de latence, mais tolère les données passées, les lectures non actualisées peuvent s'avérer avantageuses en termes de performances.
Pour choisir le type de lecture souhaité, définissez une limite d'horodatage dans la requête de lecture. Pour choisir une limite d'horodatage, suivez les bonnes pratiques ci-dessous:
Choisissez des lectures fortes autant que possible. Il s'agit de la limite d'horodatage par défaut pour les lectures Spanner, y compris les transactions en lecture seule. Il est garanti que les lectures fortes tiennent compte des effets de toutes les transactions enregistrées avant le début de l'opération, quelle que soit l'instance dupliquée recevant la lecture. De ce fait, les lectures fortes simplifient le code des applications et augmentent la fiabilité de ces dernières. Pour en savoir plus sur les propriétés de cohérence de Spanner, consultez la section TrueTime et cohérence externe.
Si, dans certaines situations, la latence empêche les lectures fortes, préférez les lectures non actualisées (obsolescence limitée ou exacte) pour améliorer les performances lorsque vous n'avez pas besoin de lectures très récentes. Comme décrit sur la page Replication (Réplication), 15 secondes est une valeur d'obsolescence raisonnable à utiliser pour obtenir de bonnes performances.
Lire des données avec un rôle de base de données
Si vous utilisez le contrôle des accès ultraprécis, vous devez sélectionner un rôle de base de données pour exécuter des instructions et des requêtes SQL, et pour effectuer des opérations sur les lignes d'une base de données. Votre sélection de rôle persiste tout au long de votre session jusqu'à ce que vous changiez de rôle.
Pour savoir comment effectuer une lecture avec un rôle de base de données, consultez la section Accéder à une base de données avec un contrôle des accès ultraprécis.
Méthodes de lecture unique
Spanner propose des méthodes de lecture unique (lecture hors du contexte d'une transaction) sur une base de données pour:
- exécuter la lecture sous forme d'une instruction de requête SQL ou à l'aide de l'API de lecture de Spanner ;
- effectuer une lecture forte à partir d'une ou de plusieurs lignes d'une table ;
- effectuer une lecture non actualisée à partir d'une ou de plusieurs lignes d'une table ;
- lire à partir d'une ou de plusieurs lignes d'un index secondaire.
Si vous souhaitez acheminer des lectures uniques vers un réplica ou une région spécifique dans une configuration d'instance multirégionale ou une configuration régionale personnalisée avec une ou plusieurs régions en lecture seule facultatives, consultez la section Lectures dirigées.
Les sections suivantes décrivent comment utiliser les méthodes de lecture à l'aide des bibliothèques clientes Spanner.
Exécuter une requête
Pour exécuter une instruction de requête SQL sur une base de données, procédez comme suit :
GoogleSQL
C++
Utilisez ExecuteQuery()
pour exécuter une instruction de requête SQL sur une base de données.
C#
Utilisez ExecuteReaderAsync()
pour interroger la base de données.
Go
Utilisez Client.Single().Query
pour interroger la base de données.
Java
Utilisez ReadContext.executeQuery
pour interroger la base de données.
Node.js
Utilisez Database.run
pour interroger la base de données.
PHP
Utilisez Database::execute
pour interroger la base de données.
Python
Utilisez Database.execute_sql
pour interroger la base de données.
Ruby
Utilisez Client#execute
pour interroger la base de données.
Pour créer une instruction SQL, consultez les documentations de référence de SQL sur la Syntaxe des requêtes et les Fonctions et opérateurs.
Effectuer une lecture forte
Pour effectuer une lecture forte de zéro ou plusieurs lignes d'une base de données, procédez comme suit.
GoogleSQL
C++
Le code permettant de lire les données est identique à l'exemple précédent sur l'interrogation de Spanner à l'aide d'une requête SQL.
C#
Le code permettant de lire les données est identique à l'exemple précédent sur l'interrogation de Spanner à l'aide d'une requête SQL.
Go
Utilisez Client.Single().Read
pour lire les lignes de la base de données.
L'exemple utilise la valeur AllKeys
pour définir une collection de clés ou de plages de clés à lire.
Java
Utilisez ReadContext.read
pour lire les lignes de la base de données.
L'exemple utilise la valeur KeySet
pour définir une collection de clés ou de plages de clés à lire.
Node.js
Utilisez Table.read
pour lire les lignes de la base de données.
L'exemple utilise la valeur keySet
pour définir une collection de clés ou de plages de clés à lire.
PHP
Utilisez Database::read
pour lire les lignes de la base de données.
L'exemple utilise la valeur keySet
pour définir une collection de clés ou de plages de clés à lire.
Python
Utilisez Database.read
pour lire les lignes de la base de données.
L'exemple utilise la valeur KeySet
pour définir une collection de clés ou de plages de clés à lire.
Ruby
Utilisez Client#read
pour lire les lignes de la base de données.
Effectuer une lecture non actualisée
L'exemple de code suivant montre comment effectuer une lecture non actualisée de zéro ou plusieurs lignes d'une base de données à l'aide d'une limite d'horodatage d'obsolescence exacte. Pour savoir comment effectuer une lecture non actualisée à l'aide d'un horodatage d'obsolescence limitée, consultez la remarque qui suit l'exemple de code. Pour en savoir plus sur les différents types de limites d'horodatage disponibles, consultez la section Limites d'horodatage.
GoogleSQL
C++
Utilisez ExecuteQuery()
avec MakeReadOnlyTransaction()
et Transaction::ReadOnlyOptions()
pour effectuer une lecture non actualisée.
C#
Interrogez la base de données à l'aide de la méthode BeginReadOnlyTransactionAsync
sur une connexion connection
en spécifiant la valeur TimestampBound.OfExactStaleness()
.
Go
Pour lire les lignes de la base de données à l'aide d'une limite d'horodatage d'obsolescence exacte, exécutez la requête Client.ReadOnlyTransaction().WithTimestampBound()
et spécifiez la valeur ExactStaleness
.
L'exemple utilise la valeur AllKeys
pour définir une collection de clés ou de plages de clés à lire.
Java
Pour lire les lignes d'une base de données à l'aide d'une limite d'horodatage d'obsolescence exacte, utilisez la méthode read
de ReadContext
et spécifiez la valeur TimestampBound.ofExactStaleness()
.
L'exemple utilise la valeur KeySet
pour définir une collection de clés ou de plages de clés à lire.
Node.js
Pour lire les lignes de la base de données à l'aide d'une limite d'horodatage d'obsolescence exacte, utilisez Table.read
avec l'option exactStaleness
.
L'exemple utilise la valeur keySet
pour définir une collection de clés ou de plages de clés à lire.
PHP
Pour lire les lignes de la base de données à l'aide d'une limite d'horodatage d'obsolescence exacte, utilisez Database::read
en spécifiant la valeur exactStaleness
.
L'exemple utilise la valeur keySet
pour définir une collection de clés ou de plages de clés à lire.
Python
Pour lire les lignes d'une base de données à l'aide d'une limite d'horodatage d'obsolescence exacte, utilisez la méthode read
de Database
snapshot
et spécifiez la valeur exact_staleness
.
L'exemple utilise la valeur KeySet
pour définir une collection de clés ou de plages de clés à lire.
Ruby
Pour lire les lignes d'une base de données à l'aide d'une limite d'horodatage d'obsolescence exacte, utilisez la méthode read
de l'instantané Client
et spécifiez la valeur staleness
(en secondes).
Effectuer une lecture à l'aide d'un index
Pour lire zéro ou plusieurs lignes d'une base de données à l'aide d'un index, procédez comme suit:
GoogleSQL
C++
Utilisez la fonction Read()
pour effectuer une lecture à l'aide d'un index.
C#
Lisez des données à l'aide de l'index en exécutant une requête qui spécifie explicitement l'index :
Go
Pour lire les lignes de la base de données à l'aide d'un index, exécutez la requête Client.Single().ReadUsingIndex
.
Java
Pour lire les lignes de la base de données à l'aide d'un index, exécutez la requête ReadContext.readUsingIndex
.
Node.js
Pour lire les lignes de la base de données à l'aide d'un index, exécutez la requête Table.read
en y spécifiant l'index.
PHP
Pour lire les lignes de la base de données à l'aide d'un index, exécutez la requête Database::read
en y spécifiant l'index.
Python
Pour lire les lignes de la base de données à l'aide d'un index, exécutez la requête Database.read
en y spécifiant l'index.
Ruby
Pour lire les lignes de la base de données à l'aide d'un index, exécutez la requête Client#read
en y spécifiant l'index.
Lire des données en parallèle
Lorsque vous effectuez des opérations de lecture ou d'interrogation groupées impliquant de très grandes quantités de données à partir de Spanner, vous pouvez utiliser l'API PartitionQuery
pour obtenir des résultats plus rapides. L'API divise la requête en lots, ou partitions, en utilisant plusieurs machines pour extraire les partitions en parallèle. N'oubliez pas que l'utilisation de l'API PartitionQuery
entraîne une latence plus élevée, car elle n'est destinée qu'aux opérations groupées telles que l'exportation ou l'analyse de l'ensemble de la base de données.
Vous pouvez effectuer n'importe quelle opération d'API de lecture en parallèle à l'aide des bibliothèques clientes de Spanner. Toutefois, vous ne pouvez partitionner les requêtes SQL que si elles sont partitionnables par racine. Pour qu'une requête puisse être partitionnée par racine, le plan de requête doit répondre à l'une des conditions suivantes:
Le premier opérateur du plan d'exécution de la requête est une union distribuée et le plan d'exécution de la requête ne contient qu'une seule union distribuée (à l'exception des unions distribuées locales). Votre plan de requête ne peut contenir aucun autre opérateur distribué, tel que distributed cross apply.
Aucun opérateur distribué n'est présent dans le plan de requête.
L'API PartitionQuery
exécute les requêtes en mode de traitement par lot. Spanner peut choisir un plan d'exécution de requêtes qui rend les requêtes partitionnables par racine lorsqu'elles sont exécutées en mode par lot. Par conséquent, l'API PartitionQuery
et Spanner Studio peuvent utiliser différents plans d'exécution de requêtes pour une même requête. Il est possible que vous ne puissiez pas obtenir le plan d'exécution de la requête utilisé par l'API PartitionQuery
sur Spanner Studio.
Pour les requêtes partitionnées comme celle-ci, vous pouvez choisir d'activer Spanner Data Boost. Data Boost vous permet d'exécuter de grandes requêtes analytiques avec un impact quasi nul sur les charges de travail existantes sur l'instance Spanner provisionnée. Les exemples de code en C++, Go, Java, Node.js et Python de cette page montrent comment activer le boost de données.
Pour en savoir plus sur Data Boost, consultez la page Présentation de Data Boost.
GoogleSQL
C++
Cet exemple extrait les partitions d'une requête SQL dans la table Singers
et exécute la requête sur chaque partition en procédant comme suit :
- Création d'une transaction par lots Spanner
- Création de partitions pour la requête, afin que les partitions puissent être réparties sur plusieurs nœuds de calcul
- Extraction des résultats de la requête pour chaque partition
C#
Cet exemple extrait les partitions d'une requête SQL dans la table Singers
et exécute la requête sur chaque partition en procédant comme suit :
- Création d'une transaction par lots Spanner
- Création de partitions pour la requête, afin que les partitions puissent être réparties sur plusieurs nœuds de calcul
- Extraction des résultats de la requête pour chaque partition
Go
Cet exemple extrait les partitions d'une requête SQL dans la table Singers
et exécute la requête sur chaque partition en procédant comme suit :
- Création d'un client Spanner et d'une transaction
- Création de partitions pour la requête, afin que les partitions puissent être réparties sur plusieurs nœuds de calcul
- Extraction des résultats de la requête pour chaque partition
Java
Cet exemple extrait les partitions d'une requête SQL dans la table Singers
et exécute la requête sur chaque partition en procédant comme suit :
- Création d'un client par lots Spanner et d'une transaction
- Création de partitions pour la requête, afin que les partitions puissent être réparties sur plusieurs nœuds de calcul
- Extraction des résultats de la requête pour chaque partition
Node.js
Cet exemple extrait les partitions d'une requête SQL dans la table Singers
et exécute la requête sur chaque partition en procédant comme suit :
- Création d'un client Spanner et d'un lot
- Création de partitions pour la requête, afin que les partitions puissent être réparties sur plusieurs nœuds de calcul
- Extraction des résultats de la requête pour chaque partition
PHP
Cet exemple extrait les partitions d'une requête SQL dans la table Singers
et exécute la requête sur chaque partition en procédant comme suit :
- Création d'un client Spanner et d'un lot
- Création de partitions pour la requête, afin que les partitions puissent être réparties sur plusieurs nœuds de calcul
- Extraction des résultats de la requête pour chaque partition
Python
Cet exemple extrait les partitions d'une requête SQL dans la table Singers
et exécute la requête sur chaque partition en procédant comme suit :
- Création d'un client Spanner et d'une transaction par lots
- Création de partitions pour la requête, afin que les partitions puissent être réparties sur plusieurs nœuds de calcul
- Extraction des résultats de la requête pour chaque partition
Ruby
Cet exemple extrait les partitions d'une requête SQL dans la table Singers
et exécute la requête sur chaque partition en procédant comme suit :
- Création d'un client par lots Spanner
- Création de partitions pour la requête, afin que les partitions puissent être réparties sur plusieurs nœuds de calcul
- Extraction des résultats de la requête pour chaque partition