2017-09-28 8 views
3

Nous étudions actuellement l'influence de l'utilisation de plusieurs familles de colonnes sur les performances de nos requêtes BigTable. Nous avons constaté que la division des colonnes en plusieurs familles de colonnes n'augmente pas les performances. Est-ce que quelqu'un a eu des expériences similaires?Familles de colonnes d'influence des performances de Bigtable

Plus de détails sur notre configuration de banc d'essai. A ce moment, chaque ligne de notre table de production contient environ 5 colonnes, chacune contenant entre 0,1 et 1 Ko de données. Toutes les colonnes sont stockées dans une famille de colonnes. Lorsque vous effectuez un filtre de plage de clés (qui renvoie en moyenne 340 lignes) et que vous appliquez un ajusteur de regex de colonne (qui renvoie seulement 1 colonne pour chaque ligne), la requête prend en moyenne 23,3 ms. Nous avons créé des tables de test où nous avons augmenté le nombre de colonnes/données par ligne d'un facteur 5. Dans le tableau de test 1, nous avons tout conservé dans une famille de colonnes. Comme prévu cela a augmenté le temps de requête de cette même requête à 40,6ms. Dans le tableau de test 2, nous avons conservé les données d'origine dans une famille de colonnes, mais les données supplémentaires ont été placées dans une autre famille de colonnes. Lors de l'interrogation de la famille de colonnes contenant les données d'origine (contenant ainsi la même quantité de données que la table d'origine), l'heure de la requête était en moyenne de 44,3 ms. Ainsi, la performance a même diminué en utilisant plus de familles de colonnes.

C'est exactement le contraire de ce à quoi on s'attendait. Par exemple. ce qui est mentionné dans les documents BigTable (https://cloud.google.com/bigtable/docs/schema-design#column_families)

Regroupement des données dans les familles de colonne permet de récupérer des données à partir d'une seule famille ou plusieurs familles, plutôt que de récupérer toutes les données de chaque ligne. Regroupez les données aussi étroitement que possible pour obtenir uniquement les informations dont vous avez besoin, mais pas plus, dans vos appels d'API les plus fréquents.

Toute personne ayant une explication à nos découvertes?

benchmark results


(edit: ajouter un peu plus de détails)

Le contenu d'une seule ligne:

Tableau 1:

  • cf1

    • col1
    • col2
    • ...
    • col25

Tableau 2:

  • cf1
    • col1
    • col2
    • ..
    • Col5
  • CF2
    • col6
    • COL7
    • ..
    • col25

L'indice de référence que nous exécutons utilise le client go. Le code qui appelle l'API semble essentiellement comme suit:

filter = bigtable.ChainFilters(bigtable.FamilyFilter(request.ColumnFamily), 
      bigtable.ColumnFilter(colPattern), bigtable.LatestNFilter(1)) 
tbl := bf.Client.Open(table) 
rr := bigtable.NewRange(request.RowKeyStart, request.RowKeyEnd) 
err = tbl.ReadRows(c, rr, func(row bigtable.Row) bool {return true}, bigtable.RowFilter(filter)) 

Répondre

0

Si vous récupérez les cellules X par ligne, il ne fait pas une différence de performance importante si ces cellules sont dans X familles de colonne séparée ou 1 famille de colonne avec X colonnes qualificatifs.

La différence de performance est si vous ne réellement besoin de cellules pour une ligne qui ont un but spécifique - vous pouvez l'éviter de sélectionner toutes les cellules de la ligne et au lieu simplement chercher une famille de colonne (en spécifiant un filter on the ReadRow call)


Un facteur plus important consiste simplement à choisir un schéma qui décrit précisément vos données. Si vous faites cela, tout gain du type ci-dessus viendra naturellement. De plus, vous éviterez d'atteindre la limite de 100 colonnes recommandée par la famille. Par exemple: imaginez que vous écrivez un logiciel de classement, et que vous voulez stocker les scores qu'un joueur a touchés pour chaque jeu et quelques détails personnels. Votre schéma pourrait être:

  • Ligne clé: nom d'utilisateur
  • Colonne famille user_info
    • Colonne Qualifier full_name
    • Colonne Qualifier password_hash
  • Colonne famille game_scores
    • colonne Qualifier candy_royale
    • colonne Qualifier clash_of_tanks

Ayant chaque jeu stocké dans une colonne distincte au sein de la famille colonne game_scores permet toutes les partitions pour qu'un utilisateur soit récupéré immédiatement sans également récupérer user_info, permet de conserver le nombre de familles de colonnes gérables, permet des séries chronologiques de scores pour chaque jeu indépendamment et d'autres avantages de refléter la nature des données.

+1

Salut @David, merci pour votre réponse. J'ai mis à jour la question avec plus de détails sur le contenu d'une ligne et la requête que nous effectuons. Comme vous pouvez le voir, nous effectuons un filtre FamilyFilter.Dans notre benchmark, nous avons récupéré ** col1 ** en appliquant un filtre FamilyFilter sur ** cf1 **, puis en effectuant un ColumnFilter qui correspond exactement à ** col1 **. Nous nous attendrions donc à ce que, pour la table 2, les requêtes soient plus rapides, car le filtre FamilyFilter retournerait moins de données. Cette hypothèse est-elle incorrecte? – krelst