Écritures
Cette page liste les types de requêtes d'écriture que vous pouvez envoyer à Bigtable et décrit quand les utiliser et quand ne pas les utiliser. Pour savoir comment agréger des données dans une cellule au moment de l'écriture, consultez Agréger les valeurs au moment de l'écriture.
L'API Data Bigtable et les bibliothèques clientes vous permettent d'écrire des données dans vos tables de manière programmatique. 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 avec les instances à un seul cluster et répliquées, avec le routage vers un cluster unique ou le 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 Écritures par lot.
Pour en savoir plus sur les limites qui s'appliquent aux requêtes d'écriture, consultez Quotas et limites.
Pour obtenir des exemples de bibliothèque cliente Cloud Bigtable concernant les requêtes d'écriture décrites 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.
Un 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, tel que 3023483279876543, est refusé. Dans cet exemple, la valeur de code temporel acceptable est 3023483279876000.
Toutes les mutations d'une même requête d'écriture ont le même code temporel, sauf si vous le remplacez. Vous pouvez définir le code temporel de toutes les mutations d'une requête d'écriture pour qu'il soit identique ou différent.
É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.
Mises à jour incrémentielles
Bigtable vous permet de créer des cellules avec un type de données aggregate. Les cellules agrégées sont optimisées lorsque vous souhaitez modifier les valeurs des cellules de tableau existantes, en agrégeant les valeurs des cellules à mesure que les données sont écrites. Les types d'agrégation suivants sont disponibles :
- Somme : incrémente un compteur ou conserve une somme cumulée.
- Minimum : envoyez un entier à une cellule. Bigtable conserve la plus petite des deux valeurs.
- Maximum : envoyez un entier à une cellule. 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, MergeToCell ou l'un des types de mutation de suppression.
Ajouter
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 inclut le nom de la famille de colonnes, le qualificatif de colonne et une valeur à ajouter ou un montant d'incrément.
Les règles sont appliquées dans l'ordre. Par exemple, si votre requête inclut une demande d'ajout de la chaîne thing à la valeur some d'une colonne, et qu'une règle ultérieure de la même requête ajoute body à cette même colonne, la valeur est modifiée deux fois en une seule écriture atomique. 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 avec 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 encodée en tant qu'entier signé big-endian de 64 bits. Bigtable traite un incrément d'une valeur vide ou inexistante comme si la valeur était nulle.
Les requêtes ReadModifyWriteRow sont atomiques. Elles ne font pas l'objet de nouvelles tentatives en cas d'échec, quelle qu'en soit la raison.
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
MutateRowavec une mutationAddToCell. Pour en savoir plus, consultez Agrégation des valeurs au moment de l'écriture.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 à cluster unique, 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. Il est impossible de réessayer une demande
ReadModifyWriteRow.Vous écrivez de grandes quantités de données et vous avez besoin que les écritures se terminent rapidement. Une requête qui lit une ligne, puis la modifie, est plus lente qu'une simple requête d'écriture. Par conséquent, ce type d'écriture n'est souvent pas la meilleure approche à grande échelle.
Par exemple, si vous souhaitez compter quelque chose qui se chiffre en millions, comme les vues de page, vous devez
MutateRowavec une mutationAddToCellpour mettre à jour vos comptes 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 demande de filtre doit inclure un ou les deux types de mutations suivants :
- 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.
Étant donné qu'une écriture conditionnelle lit la ligne pour évaluer le filtre, l'appelant doit disposer des autorisations bigtable.tables.readRows et bigtable.tables.mutateRows sur la table (ou des autorisations bigtable.authorizedViews.readRows et bigtable.authorizedViews.mutateRows équivalentes sur une vue autorisée). Pour en savoir plus, consultez Contrôle des accès.
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 d'écritures conditionnelles dans le cas d'utilisation suivant :
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. Les requêtesCheckAndModifyRowsont donc plus lentes que les requêtes d'écriture simples. Par conséquent, ce type d'écriture n'est souvent 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 n'ont pas abouti, jusqu'à ce que toutes les écritures réussissent ou que le délai de la requête soit atteint. 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 de façon lexicographique en fonction de la clé de ligne, qui est 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
MutateRowslorsque 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 du 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 le contrôle 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 un job Dataflow, Bigtable effectue automatiquement les opérations suivantes :
- Limiter le trafic pour éviter de surcharger votre cluster Bigtable
- Garantit que le cluster est suffisamment chargé pour déclencher l'autoscaling Bigtable (si activé), afin que des nœuds supplémentaires soient automatiquement ajoutés au cluster si nécessaire
Ces actions combinées empêchent la surcharge du cluster et l'échec du job. Vous n'avez pas besoin de mettre à l'échelle manuellement votre cluster en prévision de l'exécution de l'écriture par lot. Lorsque le contrôle du flux est activé, la mise à l'échelle du cluster se produit pendant le job Dataflow plutôt qu'avant. Le job peut donc prendre plus de temps à se terminer que si vous mettez à l'échelle 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 elle vous permet de profiter pleinement du contrôle du flux d'écriture par lot. Vous pouvez utiliser l'autoscaling Dataflow comme vous le feriez pour n'importe quel autre job.
Pour en savoir plus sur l'autoscaling Bigtable, consultez Autoscaling. Pour comprendre les règles de routage des profils d'application, consultez 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'un des éléments suivants :
- gcloud CLI
- Client Bigtable pour Java
Les autres bibliothèques clientes Bigtable ne sont pas encore compatibles avec l'accès autorisé aux vues.
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 directement appliquées à la table sous-jacente.
Limites de définition des vues autorisées
Dans une vue autorisée, les lignes ou colonnes dans lesquelles 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 que ceux 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 dans son intégralité.
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 qui se trouvent 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 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 vers 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 routée. Lorsque l'écriture est répliquée dans les autres clusters de l'instance, chacun de ces clusters reçoit é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. Toutefois, si une instance comporte plusieurs clusters, ce qui signifie qu'elle utilise la réplication, Bigtable est cohérent à terme. Vous pouvez obtenir une cohérence écriture-lecture en acheminant les requêtes vers le 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 général, vous créez un jeton de cohérence après l'envoi d'un lot d'écritures ou après un certain intervalle, par exemple une heure. Vous pouvez ensuite transmettre le jeton pour qu'il soit utilisé par un autre processus, tel qu'un module effectuant une demande de lecture, qui utilise le jeton pour vérifier que toutes les données ont été répliquées avant de tenter de les lire.
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 côté 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émenter des compteurs à l'aide de cellules agrégées
- Utilisez l'émulateur Bigtable.