Conception de schéma pour les données de séries temporelles

Cette page présente des concepts, des modèles et des exemples de conception de schémas pour le stockage de données de séries temporelles dans Cloud Bigtable. Avant de lire cette page, vous devez avoir pris connaissance de la présentation de Cloud Bigtable. Vous devez également savoir comment concevoir votre schéma.

Chaque fois que vous mesurez un élément et que vous enregistrez une valeur temporelle avec la mesure, vous construisez une série temporelle. Les séries temporelles nous entourent :

  • Lorsque vous examinez l'évolution de l'utilisation de la mémoire sur votre ordinateur parce que vous le trouvez lent, vous avez sous les yeux une série temporelle.

  • Lorsque vous consultez des prévisions météorologiques avec l'évolution des températures, vous observez une série temporelle.

  • Si vous êtes courtier de change et que votre travail consiste à représenter sur un graphique la moyenne mobile des prix sur 5, 10 et 30 jours pour les devises USD/JPY, vous êtes face à une série temporelle.

Les séries temporelles sont extrêmement importantes :

  • Les séries temporelles nous aident à optimiser l'utilisation des ressources, à diminuer la consommation d'énergie, à minimiser l'impact sur l'environnement et à réduire les coûts.

  • Les séries temporelles nous aident à identifier des tendances dans les données, pour montrer concrètement ce qui est arrivé dans le passé et formuler des estimations éclairées de ce qui va se produire dans le futur.

  • Les séries temporelles sont nécessaires à certaines analyses complexes et au machine learning dans des domaines tels que les services financiers, la vente au détail, les assurances, la physique et la chimie.

Ce guide fournit des stratégies détaillées et une procédure complète pour le stockage et l'interrogation de données de séries temporelles dans Cloud Bigtable.

Séries temporelles et Cloud Bigtable

Le stockage des données de séries temporelles dans Cloud Bigtable est un choix naturel. Cloud Bigtable stocke les données sous forme de colonnes non structurées dans des lignes. Chaque ligne possède une clé de ligne, et les clés de ligne sont triées de façon lexicographique.

Il existe deux méthodes couramment utilisées pour extraire des données de Cloud Bigtable :

  • Vous pouvez obtenir une seule ligne en spécifiant sa clé.
  • Vous pouvez obtenir plusieurs lignes en spécifiant une plage de clés.

Ces méthodes sont idéales pour l'interrogation de données de séries temporelles, car vous souhaitez souvent obtenir des données pour une période précise (par exemple, toutes les données de marchés du jour ou les statistiques de processeur du serveur pour les 15 dernières minutes). Cloud Bigtable est donc parfaitement adapté, d'un point de vue fonctionnel, aux séries temporelles.

Il existe évidemment des détails sur lesquels porter son attention. Pour Cloud Bigtable, le schéma associé aux données (colonnes et structure des clés de ligne) doit être conçu avec soin. Un schéma efficace entraîne des performances et une évolutivité excellentes, tandis qu'un mauvais schéma peut conduire à un système peu performant. Cependant, le schéma unique parfait qui convient le mieux à tous les cas d'utilisation n'existe pas.

La suite de cet article présente différents modèles de conception de schéma dans Cloud Bigtable. Ces modèles peuvent vous servir à concevoir le schéma idéal pour votre cas d'utilisation. Après la liste des modèles de conception de schéma et les explications associées à chacun d'entre eux, vous trouverez des exemples pour les cas d'utilisation suivants :

  • Données de marché financier
  • Métriques du serveur (par exemple, utilisation du processeur, de la mémoire et du réseau)
  • Compteurs énergétiques intelligents (faisant partie de l'Internet des objets ou IoT)

Modèles de conception de schéma pour les séries temporelles

Les modèles de conception de schéma permettant de stocker des séries temporelles dans Cloud Bigtable appartiennent aux catégories suivantes :

  • Modèles généraux
  • Modèles pour la conception des clés de ligne
  • Modèles pour la conception de colonnes de données

Modèles généraux

Utiliser des noms courts mais significatifs

Lorsque vous transférez des données depuis Cloud Bigtable, vous transférez également des métadonnées, telles que :

  • la clé de ligne ;
  • la famille de colonnes, identifiant utilisé pour regrouper les colonnes associées ;
  • le qualificatif de colonne, nom unique dans une famille de colonnes.

Par conséquent, il est important de choisir des noms évocateurs aussi courts que possible, car la taille de chaque nom compte au niveau du stockage et de la charge RPC. Par exemple, plutôt que d'utiliser CELLPHONE_NUMBER comme qualificatif de colonne, vous pouvez utiliser CELL comme abréviation courte mais significative.

Modèles pour la conception des clés de ligne

Utiliser des tables allongées et étroites

Une table allongée et étroite comporte un petit nombre d'événements par ligne, éventuellement un seul, tandis qu'une table courte et large comporte un grand nombre d'événements par ligne. Comme expliqué plus bas, les tables allongées et étroites conviennent mieux aux données de séries temporelles.

Par exemple, supposons que vous preniez la température de votre potager chaque matin. Dans cette optique, comme vous prenez la température chaque matin, une ligne par jour suffit. C'est pour cette raison que votre table est allongée et étroite. Notez que l'horodatage n'est pas le premier élément de la clé de ligne. Comme expliqué ultérieurement, l'utilisation d'un horodatage comme premier élément d'une clé de ligne peut être à l'origine de plusieurs problèmes.

Clé de ligne Données de colonne
POTAGER#20150301 TEMP:JOUR:15,7
POTAGER#20150302 TEMP:JOUR:16,1
POTAGER#20150303 TEMP:JOUR:16,0
POTAGER#20150304 TEMP:JOUR:18,3
POTAGER#20150305 TEMP:JOUR:16,6
POTAGER#20150331 TEMP:JOUR:15,7

Supposons maintenant que vous souhaitiez représenter la température de chaque mois ; auquel cas vous utiliserez une ligne par mois. L'exemple suivant montre la table courte et large obtenue :

Clé de ligne Données de colonne
POTAGER#20150301 TEMP:1:15,7 TEMP:2:16,1 TEMP:3:16,0 TEMP:4:18,3 TEMP:5:16,6 TEMP:31:15,7

Pour les séries temporelles, vous devez généralement utiliser des tables allongées et étroites. Deux raisons l'expliquent : le stockage d'un événement par ligne facilite l'exécution de requêtes sur vos données. Le stockage de nombreux événements par ligne augmente la probabilité que la taille totale de la ligne dépasse la valeur maximale recommandée (reportez-vous à la section Les lignes peuvent être longues, mais pas infinies).

À des fins d'optimisation, vous pouvez utiliser des tables courtes et larges, mais évitez d'intégrer un nombre illimité d'événements. Par exemple, si vous devez le plus souvent extraire un mois entier d'événements à la fois, la table de températures ci-dessus constitue une optimisation raisonnable : la taille de la ligne est limitée au nombre de jours du mois.

Préférer les lignes aux versions de colonne

Dans Cloud Bigtable, les colonnes peuvent posséder des versions horodatées. Par conséquent, il est théoriquement possible de stocker une série temporelle en tant qu'ensemble de versions d'une colonne. Par exemple, si vous souhaitez enregistrer le cours de clôture des actions ZXZZT chaque jour, vous pouvez disposer d'une seule colonne avec une version horodatée pour chaque jour :

Clé de ligne Données de colonne
ZXZZT COURS:ACTION (V1 01/03/15):558,40 COURS:ACTION (V2 02/03/15):571,34 COURS:ACTION (V3 03/03/15):573,64 COURS:ACTION (V4 04/03/15):573,37 COURS:ACTION (V5 05/03/15):575,33

Il ne s'agit toutefois pas de la meilleure méthode de stockage de ces données.

Par défaut, utilisez de nouvelles lignes à la place des versions de colonne. L'utilisation de plusieurs lignes, avec une seule version d'un événement sur chaque ligne, constitue le moyen le plus simple de représenter, de comprendre et d'interroger les données.

Il est acceptable d'utiliser les versions d'une colonne lorsque le cas d'utilisation modifie réellement une valeur et que l'historique de la valeur est important. Par exemple, supposons que vous ayez effectué une série de calculs basés sur le cours de clôture de ZXZZT et que, initialement, les données aient été saisies par erreur avec 559,40 pour le cours de clôture au lieu de 558,40. Dans ce cas, il peut être important de connaître l'historique de la valeur au cas où la valeur incorrecte ait causé d'autres erreurs de calcul.

Concevoir les clés de ligne dans l'optique des requêtes

Lorsque Cloud Bigtable stocke des lignes, il les trie par clé de ligne dans l'ordre lexicographique. Il existe ainsi un seul index par table : la clé de ligne. Les requêtes qui accèdent à une seule ligne ou à une plage de lignes contiguës s'exécutent rapidement et efficacement. Toutes les autres requêtes donnent lieu à une analyse complète de la table, qui est donc beaucoup plus lente. L'analyse complète de la table fonctionne comme son nom l'indique : chaque ligne de la table est examinée tour à tour. Pour Cloud Bigtable, où vous pouvez stocker plusieurs pétaoctets de données dans une seule table, les performances d'une analyse complète de la table ne font qu'empirer au fur et à mesure de la croissance du système.

Par exemple, prenons une table dans laquelle les scores des joueurs de jeux vidéo sont stockés. Elle pourrait être conçue comme suit.

Clé de ligne Données de colonne
LoL#20150301 JEU:JOUEUR:Corrie JEU:VICTOIRE:false JEU:KDA:4,25
LoL#20150302 JEU:JOUEUR:Jo JEU:VICTOIRE:true JEU:KDA:7,00
LoL#20150302 JEU:JOUEUR:Sam JEU:VICTOIRE:true JEU:KDA:7,00
LoL#20150303 JEU:JOUEUR:Corrie JEU:VICTOIRE:true JEU:KDA:9,50
Starcraft#20150303 JEU:JOUEUR:Eriko JEU:VICTOIRE:true JEU:KDA:6,00

Supposons que vous souhaitiez interroger ces données pour répondre à la question "Combien de parties de LoL ont été remportées par Corrie en mars ?" Avec le schéma présenté ci-dessus, vous devriez analyser une grande partie de la table pour répondre à cette question. En revanche, si vous concevez la table comme suit, vous pouvez compléter cette requête en récupérant une plage spécifique de clés de ligne :

Clé de ligne Données de colonne
LoL#Corrie#20150301 JEU:VICTOIRE:false JEU:KDA:4,25
LoL#Corrie#20150303 JEU:VICTOIRE:true JEU:KDA:9,50
LoL#Jo#20150302 JEU:VICTOIRE:true JEU:KDA:7,00
LoL#Sam#20150302 JEU:VICTOIRE:true JEU:KDA:7,00
Starcraft#Eriko#20150303 JEU:VICTOIRE:true JEU:KDA:6,00

Le choix d'une clé de ligne facilitant les requêtes courantes est d'une importance capitale pour les performances globales du système. Listez vos requêtes, classez-les par ordre d'importance, puis concevez des clés de ligne qui fonctionnent pour ces requêtes.

Comment gérer une situation dans laquelle la clé de ligne parfaite n'existe pas ? Par exemple, supposons que les requêtes pour toutes les parties de LoL de mars et toutes les parties de LoL jouées par Corrie en mars sont d'importance égale. Le schéma ci-dessus nous permettrait d'interroger les parties de LoL de Corrie en mars, mais ne nous aiderait pas pour l'ensemble des parties de LoL du mois. La meilleure solution est d'interroger toutes les parties de LoL, puis de filtrer sur le mois de mars. Deux options s'offrent à vous pour résoudre ce problème :

Dénormalisation

  • Utilisez deux tables, chacune avec une clé de ligne adaptée à l'une des requêtes. Cette solution est efficace, car elle produit un système robuste et évolutif.

Requête et filtre

  • Conservez le schéma présenté ci-dessus et créez une requête (toutes les parties de LoL du mois de mars) sous-performante, car vous filtrez un grand nombre de lignes. Cette solution n'est généralement pas la bonne, car elle produit un système moins évolutif, dont les performances pourraient vite chuter à mesure que l'utilisation augmente.

S'assurer que la clé de ligne évite le hotspotting

Le problème le plus courant pour les séries temporelles dans Cloud Bigtable est le hotspotting. Ce problème peut concerner tout type de clé de ligne contenant une valeur qui augmente de façon linéaire.

En résumé, lorsqu'une clé de ligne pour une série temporelle inclut un horodatage, toutes vos écritures ciblent un seul nœud, remplissent ce nœud, puis passent au prochain nœud du cluster, ce qui entraîne un hotspotting. Par exemple, si vous stockez l'état de la batterie d'un téléphone portable et que votre clé de ligne se compose du mot "BATTERIE" et d'un horodatage (comme ci-dessous), la clé de ligne augmente toujours dans l'ordre croissant. Dans la mesure où Cloud Bigtable stocke les clés de ligne adjacentes sur le même nœud de serveur, toutes les écritures se concentrent sur un seul nœud jusqu'à ce que ce nœud soit saturé. À ce stade, les écritures passent au nœud suivant du cluster.

Clé de ligne Données de colonne
BATTERIE#20150301124501001 METRIQUE:UTILISATEUR:Corrie METRIQUE:POURCENTAGE:98
BATTERIE#20150301124501002 METRIQUE:UTILISATEUR:Jo METRIQUE:POURCENTAGE:54
BATTERIE#20150301124501003 METRIQUE:UTILISATEUR:Corrie METRIQUE:POURCENTAGE:96
BATTERIE#20150301124501004 METRIQUE:UTILISATEUR:Sam METRIQUE:POURCENTAGE:43
BATTERIE#20150301124501005 METRIQUE:UTILISATEUR:Sam METRIQUE:POURCENTAGE:38

Il existe plusieurs moyens de résoudre ce problème :

  • Promotion de champ. Déplacez les champs des données de colonne dans la clé de ligne pour que les écritures ne soient pas contiguës.

  • Salage. Ajoutez un élément calculé supplémentaire à la clé de ligne pour créer artificiellement des écritures non contiguës.

L'utilisation de l'outil Key Visualizer peut vous aider à identifier les points d'accès et à faciliter la résolution des problèmes avec Cloud Bigtable.

Promotion de champ

Dans cet exemple, vous allez promouvoir USER d'une colonne en élément de la clé de ligne. Cette modification résout le problème de hotspotting, car les identifiants d'utilisateur fournissent une distribution plus uniforme des clés de ligne. Par conséquent, les écritures sont réparties sur plusieurs nœuds de votre cluster.

L'avantage de la promotion de champ réside dans le fait qu'elle rend souvent vos requêtes plus efficaces, faisant ainsi de cette stratégie une solution évidente. Le (léger) inconvénient est que vos requêtes sont limitées par les champs promus, ce qui entraîne des modifications si vous ne promouvez pas les bons champs.

Clé de ligne Données de colonne
BATTERIE#Corrie#20150301124501001 METRIQUE:POURCENTAGE:98
BATTERIE#Corrie#20150301124501003 METRIQUE:POURCENTAGE:96
BATTERIE#Jo#20150301124501002 METRIQUE:POURCENTAGE:54
BATTERIE#Sam#20150301124501004 METRIQUE:POURCENTAGE:43
BATTERIE#Sam#20150301124501005 METRIQUE:POURCENTAGE:38

Salage

Dans cet exemple, vous allez utiliser un hachage de l'horodatage et le diviser par 3, puis prendre le reste de ce calcul et l'ajouter à la clé de ligne. Pourquoi par 3 ? Il s'agit d'une estimation du nombre de nœuds du cluster concerné, qui correspond à une répartition appropriée de l'activité entre ces nœuds.

L'avantage du salage est sa simplicité : dans l'absolu, il s'agit d'une fonction de hachage. L'un de ses inconvénients est que, lorsque vous interrogez des périodes, vous devez effectuer plusieurs analyses (une analyse par valeur de salage) et combiner les résultats dans votre propre code. Par ailleurs, il est difficile de choisir une valeur de salage qui répartit l'activité entre les nœuds et fonctionne correctement lorsque vous faites évoluer le système. En raison de ces inconvénients et du fait qu'il est préférable d'utiliser des clés de ligne lisibles par un humain, évitez le salage, sauf si vous ne parvenez à trouver aucun autre moyen d'éviter le hotspotting.

Clé de ligne Données de colonne
BATTERIE#1#20150301124501003 METRIQUE:UTILISATEUR:Jo METRIQUE:POURCENTAGE:96
BATTERIE#1#20150301124501004 METRIQUE:UTILISATEUR:Sam METRIQUE:POURCENTAGE:43
BATTERIE#2#20150301124501002 METRIQUE:UTILISATEUR:Corrie METRIQUE:POURCENTAGE:54
BATTERIE#3#20150301124501005 METRIQUE:UTILISATEUR:Sam METRIQUE:POURCENTAGE:38
BATTERIE#3#20150301124501001 METRIQUE:UTILISATEUR:Corrie METRIQUE:POURCENTAGE:98

Par défaut, préférez la promotion de champ. La promotion de champ évite le hotspotting dans presque tous les cas et tend à simplifier la conception d'une clé de ligne facilitant les requêtes.

Réservez le salage aux cas dans lesquels la promotion de champ ne résout pas les problèmes de hotspotting. Dans les rares cas où vous appliquez une fonction de salage, veillez à ne pas faire trop d'hypothèses sur la taille sous-jacente du cluster. L'exemple ci-dessus applique une fonction de salage qui suppose que le cluster comporte trois nœuds. Cette hypothèse est sûre car elle s'adapte au nombre limité de nœuds pouvant exister dans un cluster Cloud Bigtable. Si vous pouviez créer des clusters avec des centaines de nœuds, vous utiliseriez une fonction de salage différente.

N'inverser les horodatages qu'en cas de nécessité

Vous pouvez inverser un horodatage en le soustrayant de la valeur maximale du langage de programmation pour les entiers longs (par exemple java.lang.Long.MAX_VALUE en Java). En inversant l'horodatage, vous pouvez concevoir une clé de ligne dans laquelle l'événement le plus récent apparaît au début de la table et non à la fin. Par conséquent, vous pouvez obtenir les N événements les plus récents simplement en extrayant les N premières lignes de la table.

Réservez les horodatages inversés aux cas dans lesquels votre requête la plus courante concerne les valeurs récentes. En effet, l'inversion des horodatages rend les autres requêtes plus complexes et complique le schéma global.

Modèles pour la conception de colonnes de données

Les lignes peuvent être longues, mais pas infinies

Dans Cloud Bigtable, les lignes peuvent contenir environ 100 familles de colonnes et des millions de colonnes, avec une limite de 100 Mo pour chaque valeur stockée dans une colonne. Ces limites généreuses offrent une grande flexibilité. Cependant, ne partez pas du principe que les longues lignes constituent le bon moyen de stocker des données et que vous devez donc remplir chaque ligne avec autant de données que possible. Gardez toujours à l'esprit que l'extraction de grandes valeurs nécessite du temps et de la mémoire.

En règle générale, maintenez les lignes à une taille inférieure à 100 Mo. Il s'agit davantage d'une ligne directrice que d'une règle : les lignes peuvent dépasser 100 Mo. Toutefois, si vous disposez de plusieurs lignes plus volumineuses, vous devez vous attendre à des problèmes de performances.

En règle générale, maintenez les colonnes à des valeurs inférieures à 10 Mo. Cette fois encore, il s'agit davantage d'une indication que d'une règle : vous pouvez stocker des valeurs supérieures à 10 Mo, mais elles risquent de poser des problèmes de performances.

Pour rappel, si vous utilisez souvent des lignes ou des valeurs individuelles volumineuses, attendez-vous à des problèmes de performances sur votre système.

Cloud Bigtable est un espace de stockage de paires clé/valeur, et non un espace de stockage relationnel. Il n'accepte ni les jointures, ni les transactions, sauf sur une même ligne. Par conséquent, il est préférable d'accéder aux données de lignes individuelles ou d'un ensemble de lignes contiguës.

L'une des conséquences de l'utilisation de ce modèle est relativement évidente : dans la grande majorité des cas, les requêtes de séries temporelles accèdent à un ensemble de données précis pour une période spécifique. De ce fait, assurez-vous que toutes les données d'une période particulière sont stockées dans des lignes contiguës, à moins que cela ne provoque du hotspotting.

Par ailleurs, avec ce modèle, lorsque vous lisez des données pour une ligne ou une plage de lignes, ces données doivent être utiles par elles-mêmes. Il ne doit pas être nécessaire de les combiner avec d'autres données. Par exemple, supposons que vous stockiez l'activité des utilisateurs sur un site Web de shopping et que vous ayez souvent besoin d'extraire les cinq dernières actions effectuées par l'utilisateur afin de les afficher dans une barre latérale. Dans ce cas, envisagez de dénormaliser vos données et d'inclure des informations sur l'utilisateur et le produit dans la table des actions récentes. En revanche, avec une base de données relationnelle, vous stockez probablement l'ID utilisateur et l'ID produit dans une table, puis joignez cette table aux tables utilisateur et produit séparément dans votre requête SQL.

Cela étant, il n'est pas nécessaire d'inclure toutes les données relatives à une entité sur chaque ligne. Par exemple, si vous affichez des informations sur les actions récentes d'un utilisateur, vous n'avez pas besoin de stocker le numéro de téléphone de l'utilisateur ou l'adresse du fabricant d'un produit, car vous n'allez pas afficher ces informations dans une barre latérale.

Recherchez les possibilités de dénormalisation des données pour répondre aux requêtes, mais n'incluez que les données requises par les requêtes.

Stocker les données auxquelles vous accéderez dans une même requête dans une famille de colonnes

Les qualificatifs de colonne d'une famille de colonnes particulière ont une relation physique et logique. En général, tous les qualificatifs de colonne d'une famille de colonnes sont stockés ensemble, consultés ensemble et mis en cache ensemble. Par conséquent, une requête qui accède à une seule famille de colonnes peut s'exécuter plus efficacement qu'une requête couvrant plusieurs familles.

Assurez-vous que vos requêtes courantes sont efficaces au maximum en extrayant des données provenant du plus petit nombre possible de familles de colonnes.

Ne pas exploiter l'atomicité des lignes uniques

Cloud Bigtable n'accepte pas les transactions, à une exception près : les opérations sur une seule ligne sont transactionnelles. Les transactions sont par ailleurs coûteuses, ce qui signifie qu'un système qui repose sur des transactions ne fonctionne pas aussi bien qu'un système sans transaction.

Lorsque vous travaillez avec des séries temporelles, n'utilisez pas le comportement transactionnel des lignes. Les modifications apportées aux données d'une ligne existante doivent être stockées en tant que nouvelle ligne séparée, sans modification de la ligne existante. Ce modèle est plus facile à construire et vous permet de conserver un historique de l'activité sans vous appuyer sur les versions de colonne.

Exemples de conception de schéma

Vous allez maintenant appliquer les modèles de conception de schéma afin de créer des exemples pour les types de données suivants :

  • Données de marché financier
  • Métriques de serveur
  • Compteurs d'énergie intelligents (Internet des objets)

N'oubliez pas qu'il s'agit d'exemples. Pour trouver le schéma le mieux adapté à vos données de séries temporelles, vous devez prendre en compte la nature des données que vous stockez et la manière dont vous envisagez de les interroger, puis appliquer les modèles de conception de la section précédente.

Données de marché financier

Cet exemple prend un message de données de marché boursier hypothétique qui représente des informations sur des actions imaginaires :

Champ Exemple de données
Symbole boursier ZXZZT
Enchère 600,55
Demande 600,60
Volume de l'offre 500
Volume de la demande 1 500
Dernière vente 600,58
Dernier volume 300
Heure de la cotation 12:53:32.156
Heure de l'opération 12:53:32.045
Exchange NASDAQ
Volume 89000

Voici quelques observations sur les messages de données de marché boursier avant de commencer :

  • Le message regroupe les données de cotation et les données d'opération, qui sont logiquement séparées.

  • Il existe un nombre relativement important (plusieurs milliers) de symboles boursiers.

  • 90 % des messages reçus correspondent à quelques centaines de ces symboles boursiers, car il y a relativement peu d'actions qui sont activement négociées.

  • Les messages arrivent fréquemment (des centaines à des dizaines de milliers par seconde), avec une moyenne de plusieurs milliers par seconde.

  • Les requêtes types concernent soit les données de cotation, soit les données d'opération, mais pas les deux à la fois.

  • Pour les données de cotation et les données d'opération, une requête type comporte les éléments suivants :

    • Une bourse (telle que NASDAQ)
    • Un symbole boursier (tel que ZXZZT)
    • Une heure de début et de fin

Vous pouvez maintenant concevoir la table associée à ce cas d'utilisation :

Conserver les données liées dans la même table, conserver les données non liées dans des tables différentes

  • Stockez les données de cotation dans une table appelée QUOTE.
  • Stockez les données d'opération dans une table appelée TRADE.
  • Les requêtes peuvent inclure des périodes arbitraires. Vous allez donc stocker les données d'un seul message sur chaque ligne.

Les lignes peuvent être longues, mais pas infinies

  • Chaque ligne stocke les données d'un seul message. Cela ne pose aucun problème de taille.

Ne pas exploiter l'atomicité de lignes uniques

  • Chaque message est autonome, ce qui ne pose aucun problème.

Utiliser des noms courts mais significatifs

  • Pour des raisons de simplicité, cet exemple utilise comme noms les champs du message, en majuscules sans espace.

De ces considérations découle la disposition de colonnes suivante :

Exemple de table QUOTE :

Données de colonne
MD:SYMBOL:ZXZZT MD:BID:
600,55
MD:ASK:
600,60
MD:BIDSIZE:
500
MD:ASKSIZE:
1500
MD:QUOTETIME:
1426535612156
MD:EXCHANGE:
NASDAQ

Exemple de table TRADE :

Données de colonne
MD:SYMBOL:
ZXZZT
MD:LASTSALE:
600,58
MD:LASTSIZE:
300
MD:TRADETIME:
1426535612045
MD:EXCHANGE:
NASDAQ
MD:VOLUME:
89000

Ensuite, concevez la clé de ligne :

Utiliser des tables allongées et étroites

  • Chaque ligne stocke les données d'un message, ce qui génère un très grand nombre de lignes relativement étroites.

Préférer les lignes aux versions de colonne

  • N'utilisez les versions de colonne que dans les cas exceptionnels où une valeur est incorrecte.

Concevoir les clés de ligne dans l'optique des requêtes

  • Les clés de ligne QUOTE et TRADE peuvent suivre le même format.
  • S'agissant d'une série temporelle, vous pouvez supposer par défaut que QUOTETIME fait partie de la clé de ligne.
  • Pour des requêtes par bourse et par symbole boursier pour des heures de début et de fin données, vous devez utiliser les valeurs de EXCHANGE, SYMBOL et QUOTETIME.
  • Par conséquent, vous allez promouvoir EXCHANGE (en tant que code à six caractères ; les noms de bourses de moins de six caractères sont complétés à droite avec des espaces), SYMBOL (en tant que code à cinq caractères ; les symboles boursiers de moins de cinq caractères sont complétés à droite avec des espaces) et QUOTETIME (en tant que nombre à 13 chiffres). En complétant EXCHANGE et SYMBOL par des espaces, vous vous assurez que chaque partie de la clé de ligne se trouve à une position prévisible.
  • En prenant ces valeurs ensemble, la clé de ligne prend le format EXCHANGE + SYMBOL + QUOTETIME (par exemple, NASDAQ#ZXZZT#1426535612156).

S'assurer que la clé de ligne évite le hotspotting

  • Avec EXCHANGE et SYMBOL en positions de tête dans la clé de ligne, l'activité est répartie naturellement.
  • Étant donné que 90 % des messages sont concentrés sur quelques centaines de symboles boursiers, il existe un risque de hotspotting. Effectuez un test de contrainte sur le système avant de procéder à de nouveaux changements. Si cette concentration entraîne des performances médiocres, vous pouvez appliquer un salage afin de distribuer plus efficacement l'activité.

N'inverser les horodatages qu'en cas de nécessité

  • Dans ce cas, vous n'inversez pas les horodatages, car les requêtes n'ont pas toujours besoin d'accéder aux données les plus récentes.

Après cet exercice de conception, vous disposez des tables suivantes :

Exemple de table QUOTE :

Clé de ligne Données de colonne
NASDAQ#ZXZZT#1426535612156 MD:SYMBOL:
ZXZZT
MD:BID:
600,55
MD:ASK:
600,60
MD:BIDSIZE:
500
MD:ASKSIZE:1
500
MD:QUOTETIME:
1426535612156
MD:EXCHANGE:
NASDAQ

Exemple de table TRADE :

Clé de ligne Données de colonne
NASDAQ#ZXZZT#1426535612045 MD:SYMBOL:
ZXZZT
MD:LASTSALE:
600,58
MD:LASTSIZE:
300
MD:TRADETIME:
1426535612045
MD:EXCHANGE:
NASDAQ
MD:VOLUME:
89000

Ces tables s'accroissent à hauteur de centaines de millions de lignes par jour, ce que Cloud Bigtable peut gérer sans difficulté.

Métriques de serveur

L'exemple suivant utilise un système de surveillance de serveur hypothétique qui collecte une grande variété de métriques (telles que l'utilisation du processeur, de la mémoire et du disque par cœur) à partir d'un vaste ensemble de machines. Vous allez passer par plusieurs itérations du schéma dans cet exemple.

Vous pouvez vous appuyer sur les hypothèses suivantes sur les données :

  • Vous collectez 100 métriques par machine.
  • Vous collectez les métriques de 100 000 machines.
  • Les métriques sont collectées toutes les cinq secondes.
  • Les requêtes types peuvent être les suivantes :

    • Métriques pour une machine spécifique, pour des heures de début et de fin données
    • Dernières métriques pour l'ensemble complet de machines

Avec ce cas d'utilisation à l'esprit, vous pouvez concevoir la table :

Itération 1

Conserver les données liées dans la même table, conserver les données non liées dans des tables différentes

  • Vous allez stocker les données des métriques dans une table appelée METRIC.
  • Il existe plusieurs catégories de métriques, que vous regroupez en utilisant les familles de colonnes appropriées.
  • Les requêtes peuvent inclure des périodes arbitraires. Chaque ligne stocke donc un seul ensemble de métriques d'une machine à une heure donnée.

Les lignes peuvent être longues, mais pas infinies

  • Chaque ligne stocke un seul ensemble de métriques, ce qui ne pose aucun problème de taille.

Ne pas exploiter l'atomicité de lignes uniques

  • Cette conception de schéma n'implique pas l'atomicité des lignes.

Utiliser des noms courts mais significatifs

  • Pour des raisons de simplicité, vous utilisez les noms de champ des métriques, en majuscules sans espace, en tant que noms des qualificatifs de colonne.

De ces considérations découle la disposition de colonnes suivante :

Données de colonne
METRIC:
HOSTNAME:
server1.bbb.com
METRIC:
CPU/CPU1_USR:
0,02
METRIC:
CPU/CPU1_NICE:
0,00
METRIC:
IO/BLK_READ:
253453634
METRIC:
MIO/BLK_WRTN:
657365234

Ensuite, concevez la clé de ligne en fonction des modèles :

Utiliser des tables allongées et étroites

  • Chaque ligne de la table stocke un ensemble de métriques pour une machine, ce qui donne un très grand nombre de lignes.

Préférer les lignes aux versions de colonne

  • Vous n'utilisez pas les versions de colonne.

Concevoir les clés de ligne dans l'optique des requêtes

  • Comme il s'agit d'une série temporelle, incluez l'horodatage TS dans la clé de ligne.
  • Pour extraire les métriques d'une machine spécifique pour des heures de début et de fin données, vous extrayez une plage de lignes à l'aide de HOSTNAME plus TS.
  • L'extraction des dernières métriques pour l'ensemble des machines est complexe. Vous ne pouvez pas simplement inverser l'horodatage et analyser N lignes, car rien ne garantit que chaque machine de l'ensemble sera récupérée.

Vous rencontrez à présent un problème avec la conception de la clé de ligne. La solution ici est la dénormalisation. Vous allez créer une table séparée contenant les dernières versions des métriques, appelée CURRENT_METRIC, mise à jour en même temps que METRIC. Lorsque vous mettez à jour les métriques existantes pour une machine, vous écrasez simplement la ligne de cette machine.

Ensuite, repassez sur votre conception d'origine :

Itération 2

Conserver les données liées dans la même table, conserver les données non liées dans des tables différentes

  • Vous allez stocker les données des métriques dans une table appelée METRIC.
  • Vous allez stocker la dernière version des métriques dans une table appelée CURRENT_METRIC.
  • Les autres informations restent les mêmes que dans l'itération 1.

Les lignes peuvent être longues, mais pas infinies

  • Comme dans l'itération 1.

Ne pas exploiter l'atomicité de lignes uniques

  • Vous vous appuyez sur l'atomicité des lignes pour mettre à jour les données de chaque machine dans CURRENT_METRIC. Il s'agit d'une simple mutation de ligne, avec un faible potentiel de conflit, et qui ne cause donc aucun problème.

Utiliser des noms courts mais significatifs

  • Comme dans l'itération 1.

Ensuite, concevez la clé de ligne en fonction des modèles :

Utiliser des tables allongées et étroites

  • Dans les deux tables, chaque ligne de la table stocke un ensemble de métriques pour une machine, ce qui donne un grand nombre de lignes.

Préférer les lignes aux versions de colonne

  • Comme dans l'itération 1.

Concevoir les clés de ligne dans l'optique des requêtes

  • Comme il s'agit d'une série temporelle, incluez l'horodatage TS dans la clé de ligne. Pour extraire les métriques d'une machine spécifique pour des heures de début et de fin données, vous extrayez une plage de lignes de METRIC à l'aide de HOSTNAME plus TS.
  • Par conséquent, vous allez promouvoir HOSTNAME en tant que clé de ligne et utiliser une clé au format HOSTNAME + TS.
  • Pour rechercher les dernières métriques de machines spécifiques, analysez CURRENT_METRIC, en filtrant le préfixe de clé de ligne ou le HOSTNAME de ces machines.
  • Pour rechercher les dernières métriques de l'inventaire complet des machines, analysez CURRENT_METRIC sans spécifier de clé de ligne.
  • Par conséquent, il n'est pas nécessaire de promouvoir des champs supplémentaires vers la clé de ligne, et celle-ci prend le format simple HOSTNAME + TS. Cela conduit à un schéma simple, facile à comprendre, qui permet de segmenter efficacement les tables.
  • Dans la table CURRENT_METRIC, vous n'avez plus besoin de l'horodatage. La clé de ligne sera donc HOSTNAME.

    Exemple de clé de ligne pour METRIC : server1.aaa.bbb.com#1426535612045

    Exemple de clé de ligne pour CURRENT_METRIC : server1.aaa.bb.com

S'assurer que la clé de ligne évite le hotspotting

  • Pour METRIC et CURRENT_METRIC, le hotspotting ne représente pas un problème, car le nom d'hôte situé au début de la clé de ligne répartit l'activité entre les régions.

N'inverser les horodatages qu'en cas de nécessité

  • Vous stockez les données pour les métriques les plus récentes dans une table distincte. Vous n'avez donc pas besoin d'inverser l'horodatage.

Après l'exercice de conception, vous obtenez ce qui suit :

Table METRIC :

Clé de ligne Données de colonne
server1.bbb.com#1426535612045 METRIC:
CPU/CPU1_USR:
0,02
METRIC:
CPU/CPU1_NICE:
0,00
METRIC:
IO/BLK_READ:
253453634
METRIC:
MIO/BLK_WRTN:
657365234

Cette table croît à hauteur d'environ deux milliards de lignes par jour, ce que Cloud Bigtable peut gérer sans difficulté.

Table CURRENT_METRIC :

Clé de ligne Données de colonne
server1.bbb.com METRIC:
CPU/CPU1_USR:
0,02
METRIC:
CPU/CPU1_NICE:
0,00
METRIC:
IO/BLK_READ:
253453634
METRIC:
MIO/BLK_WRTN:
657365234

Compteurs d'énergie intelligents (Internet des objets)

Cet exemple utilise un scénario IdO hypothétique dans lequel des compteurs d'énergie intelligents envoient régulièrement les relevés de capteur à un système centralisé. Une fois encore, vous allez passer par plusieurs itérations du schéma dans cet exemple.

Vous pouvez vous appuyer sur les hypothèses suivantes sur les données :

  • Les compteurs opérationnels sont au nombre de 10 000 000.
  • Chaque compteur envoie un relevé de capteur toutes les 15 minutes.
  • L'ID du compteur est un ID numérique unique.
  • Les requêtes types peuvent être les suivantes :

    • Toutes les données d'un compteur spécifique pour un jour donné
    • Toutes les données pour un jour donné

Selon ce cas d'utilisation, vous pouvez concevoir la table :

Conserver les données liées dans la même table, conserver les données non liées dans des tables différentes

  • Vous allez stocker les données de capteur dans une table appelée SENSOR.
  • Les requêtes sont incrémentées quotidiennement, de sorte que chaque ligne stocke des données pour un compteur sur une journée.

Les lignes peuvent être longues, mais pas infinies

  • Chaque ligne contient les données d'un compteur pour une journée, soit un total de 96 colonnes (24 heures par jour * 60 minutes par heure / 1 relevé toutes les 15 minutes), ce qui ne pose pas de problème de taille.

Ne pas exploiter l'atomicité de lignes uniques

  • Vous allez ici exploiter l'atomicité des lignes, car lorsque les données sont reçues, elles sont ajoutées à la ligne quotidienne appropriée. Il s'agit d'une simple mutation de ligne, avec un faible potentiel de conflit, et qui ne cause donc aucun problème.

Utiliser des noms courts mais significatifs

  • ID stocke l'ID du compteur (entier unique).
  • Une série de colonnes portant les noms 0000 à 2345 contient les 96 valeurs enregistrées toutes les 15 minutes dans la journée. Ce schéma est adopté car il permet si nécessaire de passer à d'autres intervalles que celui de 15 minutes.

De ces considérations découle la disposition de colonnes suivante :

Itération 1

Données de colonne
METER:ID:987654 METER:0000:
12,34
METER:0015:
13,45
METER:2330:
27,89
METER:2345:
28,90

Ensuite, concevez la clé de ligne :

Utiliser des tables allongées et étroites

  • Chaque ligne stocke les données d'une journée, comme indiqué précédemment.

Préférer les lignes aux versions de colonne

  • N'utilisez les versions de colonne que dans les cas exceptionnels où une valeur est incorrecte.

Concevoir les clés de ligne dans l'optique des requêtes

  • Comme il s'agit d'une série temporelle, incluez DATE dans la clé de ligne. Comme vous n'attendez qu'un degré de précision au jour près, les cinq derniers chiffres de l'horodatage sont des zéros et sont donc omis.
  • Pour interroger un compteur spécifique sur un jour donné, vous extrayez une seule ligne à l'aide de METER et DATE.
  • Pour interroger tous les compteurs sur un jour donné, extrayez une plage de lignes à l'aide de DATE.
  • Par conséquent, vous allez promouvoir DATE (sous forme de nombre à huit chiffres) et METER (sous forme de nombre à 10 chiffres, avec la valeur ID du compteur complétée à gauche pour obtenir 10 chiffres, ceci afin de pouvoir gérer un milliard de compteurs potentiels tout en conservant l'ordre lexicographique).
  • En prenant les requêtes ensemble, la clé de ligne prend le format DATE + METER. Par exemple : |20170726|0000987654|.

À ce stade, vous pouvez constater un problème : au début de chaque journée, tous les compteurs écrivent sur un seul nœud, car la date se trouve en première position dans la clé de ligne. Avec 10 millions de compteurs, il est probable que ce problème ait un impact sur les performances chaque jour. La solution consiste à trouver un meilleur moyen d'interroger les données des compteurs pour un jour spécifique. Si vous exécutez une seule requête chaque nuit et stockez les résultats dans une nouvelle table, appelée SENSOR_YYYYMMDD, vous n'avez pas besoin d'optimiser la clé de ligne pour les requêtes basées sur la date.

Résolvons ce problème par une itération :

Itération 2

Conserver les données liées dans la même table, conserver les données non liées dans des tables différentes

  • Stockez les données de capteur dans une table appelée SENSOR.
  • Les requêtes extraient les données selon des incréments quotidiens, de sorte que chaque ligne stocke des données pour un compteur sur une journée.
  • Vous exécutez une requête par lot pendant la nuit qui produit une autre table appelée SENSOR_YYYYMMDD (date) pour stocker toutes les données de compteur de cette date.

Les lignes peuvent être longues, mais pas infinies

  • Comme dans l'itération 1.

Ne pas exploiter l'atomicité de lignes uniques

  • Comme dans l'itération 1.

Utiliser des noms courts mais significatifs

  • Comme dans l'itération 1.

En réunissant tous ces éléments, l'exemple de ligne ressemble à ce qui suit pour la table SENSOR et les tables SENSOR_YYYYMMDD :

Données de colonne
METER:ID:987654 METER:0000:
12,34
METER:0015:
13,45
METER:2330:
27,89
METER:2345:
28,90

Ensuite, concevez la clé de ligne :

Utiliser des tables allongées et étroites

  • Comme dans l'itération 1.

Préférer les lignes aux versions de colonne

  • Comme dans l'itération 1.

Concevoir les clés de ligne dans l'optique des requêtes

  • Comme il s'agit d'une série temporelle, incluez DATE dans la clé de ligne.
  • Pour interroger un compteur spécifique sur un jour donné, vous extrayez une seule ligne à l'aide de METER et DATE.
  • Par conséquent, vous allez promouvoir DATE (sous forme de nombre à huit chiffres) et METER (sous forme de nombre à 10 chiffres, avec la valeur ID du compteur complétée à gauche pour obtenir 10 chiffres, ceci afin de pouvoir gérer un milliard de compteurs potentiels tout en conservant l'ordre lexicographique).
  • La clé de ligne doit prendre le format METER + DATE (par exemple, "0000987654#20170726"), ce qui est compatible avec notre requête et permet une bonne répartition de l'activité entre les nœuds.
  • Vous exécutez également une requête par lot une fois par jour, qui analyse la table entière et stocke les données de la veille dans une nouvelle table appelée SENSOR_YYYYMMDD, où YYYYMMDD correspond à la date de la veille.

S'assurer que la clé de ligne évite le hotspotting

  • Le hotspotting n'est pas une préoccupation pour la table SENSOR. Les écritures sont réparties uniformément car la clé de ligne présente METER en position de tête.
  • Le hotspotting n'est pas une préoccupation pour les tables SENSOR_YYYYMMDD. Chaque table est construite une seule fois, sous forme de requête par lot, avec des préoccupations moindres sur les performances. Toutefois, la création de ces tables nécessite une analyse complète de la table SENSOR. Vous devrez donc envisager de créer les tables SENSOR_YYYYMMDD lorsque les flux de requêtes sur la table SENSOR sont les moins importants.

N'inverser les horodatages qu'en cas de nécessité

  • Dans ce cas, vous n'avez pas besoin d'inverser les horodatages.

Après l'exercice de conception, vous disposez des éléments suivants pour la table SENSOR et les tables SENSOR_YYYYMMDD :

Clé de ligne Données de colonne
0000987654#20170726 METER:ID:987654 METER:0000:
12,34
METER:0015:
13,45
METER:2330:
27,89
METER:2345:
8,90

Cette table croît à hauteur de moins de 10 millions de lignes par jour, ce que Cloud Bigtable peut gérer sans difficulté.

Étapes suivantes