Écritures
Cette page répertorie les types de requêtes d'écriture que vous pouvez envoyer à Bigtable et précise les cas où il est opportun ou non de les utiliser. Pour en savoir plus sur l'agrégation de données dans une cellule au moment de l'écriture, consultez la section Agrégation des valeurs au moment de l'écriture.
Les API de données et les bibliothèques clientes de Bigtable vous permettent d'écrire des données dans vos tables de manière automatisée. Bigtable renvoie une réponse ou un accusé de réception pour chaque écriture.
Chaque bibliothèque cliente offre la possibilité d'envoyer les types de requêtes d'écriture suivants :
- Écritures simples
- Incréments et ajouts
- Écritures conditionnelles
- Écritures par lot
Les bibliothèques clientes Bigtable disposent d'une fonctionnalité intégrée de nouvelles tentatives d'exécution intelligentes pour les écritures simples et par lot, ce qui signifie qu'elles gèrent les indisponibilités temporaires de manière fluide. Par exemple, si votre application tente d'écrire des données et rencontre une panne ou un problème de réseau temporaires, elle procède automatiquement à une nouvelle tentative d'exécution, jusqu'à ce que l'écriture soit effective ou que l'échéance de la requête soit atteinte. Cette résilience fonctionne à la fois avec les instances à cluster unique et répliquées, et avec un routage à cluster unique ou un routage multicluster.
Pour les opérations d'écriture par lot et en flux continu, vous pouvez utiliser le connecteur Bigtable Beam. Pour en savoir plus, consultez la section Écritures par lot.
Pour en savoir plus sur les limites qui s'appliquent aux requêtes d'écriture, consultez la page Quotas et limites.
Pour obtenir des exemples de requêtes d'écriture de la bibliothèque cliente Cloud Bigtable décrits sur cette page, consultez Exemples d'écriture.
Types d'écritures et cas d'utilisation
Toutes les requêtes d'écriture incluent les composants de base suivants :
- Le nom de la table sur laquelle écrire
- Un ID de profil d'application, qui indique à Bigtable comment acheminer le trafic
- Une ou plusieurs mutations. Une mutation se compose des éléments suivants :
- Nom de la famille de colonnes
- Le qualificatif de colonne
- Timestamp
- La valeur que vous écrivez dans la table.
La valeur par défaut de l'horodatage d'une mutation correspond à la date et l'heure actuelles, mesurées en temps écoulé depuis l'epoch Unix, soit le 1er janvier 1970 à 00:00:00 UTC.
Le code temporel que vous envoyez à Bigtable doit être exprimé en microsecondes avec une précision maximale de l'ordre de la milliseconde. Un code temporel avec une précision de l'ordre de la microseconde, comme 3023483279876543
, est refusé. Dans cet exemple, la valeur de code temporel acceptable est 3023483279876000
.
Toutes les mutations d'une requête d'écriture ont le même horodatage, sauf si vous les remplacez. Vous pouvez définir l'horodatage de toutes les mutations d'une requête d'écriture afin qu'elles soient identiques, ou différentes les unes des autres.
Écritures simples
Vous pouvez écrire une seule ligne dans Bigtable à l'aide d'une requête MutateRow
incluant le nom de la table, l'ID du profil d'application à utiliser, une clé de ligne et jusqu'à 100 000 mutations pour cette ligne. Une écriture sur une seule ligne est atomique. Utilisez ce type d'écriture lorsque vous effectuez plusieurs mutations sur une seule ligne.
Pour obtenir des exemples de code montrant comment envoyer des requêtes d'écriture simples, consultez la section Effectuer une écriture simple.
Cas pour lesquels les écritures simples ne sont pas recommandées
Les écritures simples ne sont pas le meilleur moyen d'écrire des données pour les cas d'utilisation suivants :
Lorsque vous écrivez un lot de données qui aura des clés de ligne contiguës. Dans ce cas, il est recommandé d'utiliser des écritures par lot plutôt que des écritures simples consécutives, car un lot contigu peut être appliqué dans un seul appel de backend.
Lorsque vous souhaitez un débit élevé (en lignes par seconde ou octets par seconde) et n'avez pas besoin d'une latence faible. Les écritures par lot seront plus rapides dans ce cas.
Agrégations, y compris les incréments
Les agrégations sont des cellules de table Bigtable qui agrégent les valeurs des cellules au fur et à mesure de l'écriture des données. Les types d'agrégation suivants sont disponibles:
- Somme : incrémentez un compteur ou conservez une somme cumulée.
- Minimum : envoyez un entier à une cellule. Bigtable conserve la valeur la plus basse entre la valeur actuelle de la cellule et la valeur envoyée, ou la valeur envoyée si la cellule n'existe pas encore.
- Maximum : envoyez un entier à une cellule contenant une valeur. Bigtable conserve la valeur la plus élevée des deux.
- HyperLogLog (HLL) : envoyez une valeur qui est ajoutée à un ensemble probabiliste de toutes les valeurs ajoutées à la cellule.
Les requêtes de mise à jour des cellules agrégées sont envoyées avec une requête MutateRow
et un type de mutation AddToCell
ou MergeToCell
, ou l'un des types de mutation de suppression. Pour en savoir plus sur les familles de colonnes agrégées et les types d'agrégation, consultez Valeurs agrégées au moment de l'écriture.
Ajouts
Pour ajouter des données à une valeur existante, vous pouvez utiliser une requête ReadModifyWriteRow
.
Cette requête inclut le nom de la table, l'ID du profil d'application à utiliser, une clé de ligne et un ensemble de règles à utiliser lors de l'écriture des données. Chaque règle comprend le nom de la famille de colonnes, le qualificatif de colonne, ainsi qu'une valeur d'ajout ou un montant d'incrément.
Les règles sont appliquées dans l'ordre. Par exemple, si votre requête inclut une requête d'ajout de la valeur d'une colonne contenant la valeur some
avec la chaîne thing
, et qu'une règle ultérieure comprise dans la même requête ajoute cette même colonne avec body
, la valeur est modifiée deux fois dans une seule écriture atomique, et la valeur résultante est somethingbody
. La règle ultérieure ne remplace pas la règle précédente.
Vous pouvez également incrémenter un entier à l'aide d'un appel ReadModifyWriteRow
, mais nous vous recommandons d'utiliser plutôt des cellules agrégées et AddToCell
ou MergeToCell
.
Une valeur ne peut être incrémentée à l'aide de ReadModifyWrite
que si elle est codée sous la forme d'un entier signé en mode big-endian de 64 bits. Bigtable procède à l'incrémentation d'une valeur vide, ou qui n'existe pas, comme si la valeur était zéro.
Les requêtes ReadModifyWriteRow
sont atomiques. Si elles échouent pour une raison quelconque, elles ne peuvent pas faire l'objet de nouvelles tentatives d'exécution.
Quand ne pas utiliser ReadModifyWriteRow
?
N'envoyez pas de requêtes ReadModifyWriteRow
dans les situations suivantes:
Votre cas d'utilisation peut être géré en envoyant une requête
MutateRow
avec une mutationAddToCell
. Pour en savoir plus, consultez la section Agrégations.Lorsque vous utilisez un profil d'application comportant un routage multicluster.
Lorsque vous utilisez plusieurs profils d'application comportant un seul cluster et que vous envoyez des écritures susceptibles d'entrer en conflit avec des données écrites sur la même ligne et la même colonne dans d'autres clusters de l'instance. Avec le routage à un seul cluster, une requête d'écriture est envoyée à un seul cluster, puis répliquée.
Lorsque vous vous basez sur la fonctionnalité de nouvelles tentatives d'exécution intelligentes fournie par les bibliothèques clientes. Vous ne pouvez pas réessayer une requête
ReadModifyWriteRow
.Lorsque vous écrivez de grandes quantités de données et que vous avez besoin que ces écritures soient effectives rapidement. Une requête qui lit, puis modifie une ligne est plus lente qu'une requête d'écriture simple. En conséquence, ce type d'écriture ne constitue généralement pas la meilleure approche à grande échelle.
Par exemple, si vous souhaitez compter des éléments se chiffrant en millions, comme les pages vues, vous devez
MutateRow
avec une mutationAddToCell
pour mettre à jour vos totaux au moment de l'écriture.
Écritures conditionnelles
Si vous souhaitez rechercher une condition dans une ligne, puis, en fonction du résultat, écrire des données dans cette ligne, envoyez une requête CheckAndMutateRow
. Ce type de requête comprend une clé de ligne et un filtre de ligne. Un filtre de ligne est un ensemble de règles utilisé pour vérifier la valeur des données existantes. Les mutations ne sont ensuite attribuées à des colonnes spécifiques de la ligne que lorsque certaines conditions, vérifiées par le filtre, sont remplies. Ce processus de vérification puis d’écriture s'effectue en une seule action atomique.
Une requête de filtre doit inclure au moins l'un de ces types de mutations:
- Les vraies mutations, à appliquer si le filtre renvoie une valeur
- Les fausses mutations, qui sont appliquées si le filtre ne renvoie rien
Vous pouvez fournir jusqu'à 100 000 mutations de chaque type (vraies et fausses) en une seule écriture, et vous devez en envoyer au moins une. Bigtable envoie une réponse lorsque toutes les mutations sont terminées.
Pour obtenir des exemples de code montrant comment envoyer des écritures conditionnelles, consultez la section Écrire une valeur de manière conditionnelle.
Cas pour lesquels les écritures conditionnelles ne sont pas recommandées
Vous ne pouvez pas utiliser les écritures conditionnelles dans les cas suivants :
Lorsque vous utilisez un profil d'application comportant un routage multicluster.
Lorsque vous utilisez plusieurs profils d'application comportant un seul cluster et que vous envoyez des écritures susceptibles d'entrer en conflit avec des données écrites sur la même ligne et la même colonne dans d'autres clusters de l'instance. Avec le routage à un seul cluster, une requête d'écriture est envoyée à un seul cluster, puis répliquée.
Lorsque vous écrivez de grandes quantités de données et que vous avez besoin que ces écritures soient effectives rapidement. Comme pour
ReadModifyWriteRow
, les requêtes d'écriture conditionnelles doivent lire les lignes avant de les modifier. Par conséquent, les requêtesCheckAndModifyRow
sont plus lentes que les requêtes d'écriture simples. En conséquence, ce type d'écriture ne constitue généralement pas la meilleure approche à grande échelle.
Écritures par lot
Vous pouvez écrire plusieurs lignes avec un seul appel à l'aide d'une requête MutateRows
. Les requêtes MutateRows
contiennent un ensemble de 100 000 entrées au maximum, chacune appliquée de manière atomique. Chaque entrée se compose d'une clé de ligne et d'au moins une mutation à appliquer à la ligne. Une requête d'écriture par lot peut contenir jusqu'à 100 000 mutations réparties sur toutes les entrées. Par exemple, une écriture par lot peut inclure l'une des permutations suivantes :
- 100 000 entrées avec une mutation dans chaque entrée
- Une entrée avec 100 000 mutations
- 1 000 entrées avec 100 mutations chacune
Chaque entrée d'une requête MutateRows
est atomique, mais la requête dans son ensemble ne l'est pas. Si nécessaire, Bigtable réessaie toutes les entrées du lot qui ne réussissent pas, jusqu'à ce que toutes les écritures réussissent ou que la date limite de la requête soit atteinte. Il renvoie ensuite une réponse identifiant chaque écriture dans le lot et indiquant si l'écriture a réussi ou non.
Pour obtenir des exemples de code montrant comment envoyer des écritures par lot, consultez la page Effectuer des écritures par lot.
Cas pour lesquels les écritures par lot ne sont pas recommandées
Lorsque vous écrivez des données groupées sur des lignes qui ne sont pas proches les unes des autres. Bigtable stocke les données triées de façon lexicographique par clé de ligne, l'équivalent binaire de l'ordre alphabétique. Par conséquent, lorsque les clés de ligne d'une requête ne sont pas similaires, Bigtable les traite de manière séquentielle, et non en parallèle. Le débit sera élevé, mais le temps de latence le sera également. Pour éviter cela, utilisez
MutateRows
lorsque les clés de ligne sont similaires afin que Bigtable écrive des lignes proches les unes des autres. UtilisezMutateRow
, ou les écritures simples, pour les lignes qui ne sont pas à proximité les unes des autres.Lorsque vous demandez plusieurs mutations sur une même ligne. Dans ce cas, vous obtiendrez de meilleures performances si vous effectuez toutes les mutations dans une seule requête d'écriture simple. En effet, dans une écriture simple, toutes les modifications sont appliquées dans une seule action atomique, tandis qu'une écriture par lot force à sérialiser les mutations sur la même ligne, ce qui entraîne une latence.
Contrôle de flux d'écriture par lot
Si vous envoyez vos écritures par lot (y compris les suppressions) à l'aide de l'un des éléments suivants, vous pouvez activer la gestion du flux d'écriture par lot dans votre code.
- Connecteur Bigtable Beam (
BigtableIO
) - Bibliothèque cliente Bigtable pour Java
- Connecteur Beam Bigtable HBase (
CloudBigtableIO
) - Client Bigtable HBase pour Java
Lorsque le contrôle du flux d'écriture par lot est activé pour une tâche Dataflow, Bigtable effectue automatiquement les opérations suivantes :
- Limite le débit du trafic pour éviter de surcharger votre cluster Bigtable
- S'assure que le cluster est suffisamment chargé pour déclencher l'autoscaling Bigtable (si activé), afin que d'autres nœuds soient automatiquement ajoutés au cluster si nécessaire
Ces actions combinées empêchent la surcharge du cluster et l'échec des tâches. Vous n'avez pas besoin d'ajuster manuellement la taille de votre cluster en prévision de l'exécution de l'écriture par lot. Lorsque le contrôle de flux est activé, le scaling du cluster se produit pendant la tâche Dataflow plutôt qu'avant elle. La tâche peut donc prendre plus de temps à se terminer que si vous effectuez le scaling de votre cluster manuellement.
Vous devez utiliser un profil d'application configuré pour le routage à cluster unique. L'activation de l'autoscaling Bigtable pour le cluster de destination n'est pas obligatoire, mais l'autoscaling vous permet de profiter pleinement du contrôle du flux d'écriture par lot. Vous pouvez utiliser l'autoscaling Dataflow comme vous le feriez avec n'importe quelle autre tâche.
Pour en savoir plus sur l'autoscaling Bigtable, consultez la page Autoscaling. Pour comprendre les règles de routage des profils d'application, consultez la section Présentation des profils d'application.
Pour obtenir des exemples de code, consultez Activer le contrôle du flux d'écriture par lot.
Écrire des données dans une vue autorisée
Pour écrire des données dans une vue autorisée, vous devez utiliser l'une des méthodes suivantes:
- CLI gcloud
- Client Bigtable pour Java
Les autres bibliothèques clientes Bigtable ne sont pas encore compatibles avec l'accès aux vues autorisé.
Lorsque vous écrivez des données dans une vue autorisée, vous fournissez l'ID de la vue autorisée en plus de l'ID de la table.
Toutes les écritures dans une vue autorisée sont appliquées directement au tableau sous-jacent.
Limites de la définition des vues autorisées
Dans une vue autorisée, les lignes ou colonnes auxquelles vous pouvez écrire des données sont limitées par la définition de la vue autorisée. En d'autres termes, vous ne pouvez écrire que dans les lignes et les colonnes qui répondent aux mêmes critères spécifiés pour la vue autorisée.
Par exemple, si la vue autorisée est définie par le préfixe de clé de ligne examplepetstore1
, vous ne pouvez pas écrire de données à l'aide d'une clé de ligne examplepetstore2
. Le début de la valeur de la clé de ligne doit inclure la chaîne examplepetstore1
entière.
De même, si la vue autorisée est définie par le préfixe de qualificatif de colonne order-phone
, vous pouvez écrire des données à l'aide du qualificatif de colonne order-phone123
, mais vous ne pouvez pas utiliser le qualificatif de colonne order-tablet
.
Votre requête d'écriture ne peut pas non plus faire référence à des données situées en dehors de la vue autorisée, par exemple lorsque vous recherchez une valeur dans une requête d'écriture conditionnelle.
Pour toute requête qui écrit ou fait référence à des données en dehors de la vue autorisée, un message d'erreur PERMISSION_DENIED
est renvoyé.
Réplication
Lorsqu'un cluster d'une instance répliquée reçoit une écriture, celle-ci est immédiatement répliquée sur les autres clusters de l'instance.
Atomicité
Chaque requête MutateRows
que vous envoyez à une instance répliquée est validée en tant qu'action atomique unique sur le cluster vers lequel la requête est acheminée. Lorsque l'écriture est répliquée sur les autres clusters de l'instance, ces clusters reçoivent également l'écriture en tant qu'opération atomique. Les clusters ne reçoivent pas de mutations partielles. Une mutation réussit ou échoue de manière atomique pour toutes les cellules qu'elle modifie.
Cohérence
Le délai nécessaire avant que les données écrites soient disponibles dépend de plusieurs facteurs, tels que le nombre de clusters dans votre instance et le type de routage utilisé par votre profil d'application.
Avec une instance à un seul cluster, les données peuvent être lues immédiatement, mais si une instance dispose de plusieurs clusters, et qu'elle utilise alors la réplication, Bigtable est cohérent à terme. Vous pouvez obtenir une cohérence de type "lecture de vos écritures" en acheminant les requêtes vers un même cluster.
Vous pouvez créer et utiliser un jeton de cohérence et appeler CheckConsistency
en mode StandardReadRemoteWrites
après avoir envoyé des requêtes d'écriture. Le jeton vérifie la cohérence de la réplication. En règle générale, la création d'un jeton de cohérence intervient soit après l'envoi d'un lot d'écritures, soit après un certain intervalle, par exemple une heure. Vous pouvez ensuite laisser le jeton être utilisé par un autre processus, tel qu'un module effectuant une requête de lecture, qui utilise le jeton pour vérifier que toutes les données ont été répliquées avant la tentative de lecture.
Si vous utilisez un jeton juste après sa création, quelques minutes peuvent être nécessaires pour vérifier la cohérence lors de sa première utilisation. Ce délai est dû au fait que chaque cluster vérifie tous les autres afin de s'assurer qu'il ne reste plus de données qui arrivent. Après la première utilisation, ou si vous attendez plusieurs minutes pour utiliser le jeton pour la première fois, le jeton réussit immédiatement sa vérification à chaque utilisation.
Résolution de conflits
Chaque valeur de cellule d'une table Bigtable est identifiée de manière unique par le quatre-tuple (clé de ligne, famille de colonnes, qualificatif de colonne, horodatage). Pour en savoir plus sur ces identifiants, consultez la section Modèle de stockage de Bigtable. Dans les rares cas où deux écritures avec exactement le même quatre-tuple sont envoyées à deux clusters différents, Bigtable résout automatiquement le conflit à l'aide d'un algorithme interne qui stipule que la dernière écriture l'emporte, en se basant sur l'heure du serveur. La mise en œuvre de "la dernière écriture l'emporte" de Bigtable est déterministe. Lorsque la réplication rattrape le retard, tous les clusters ont la même valeur pour le quatre-tuple.
Étape suivante
- Découvrez la conception de schémas.
- Implémentez des compteurs à l'aide de cellules agrégées.
- Utilisez l'émulateur Bigtable.