Quelle est la différence entre le partitionnement et le compartimentage d'une table dans Hive?

129

Je sais que les deux sont effectués sur une colonne du tableau, mais en quoi chaque opération est-elle différente.

NishM
la source

Réponses:

247

Le partitionnement des données est souvent utilisé pour répartir la charge horizontalement, ce qui présente des avantages en termes de performances et aide à organiser les données de manière logique. Exemple : si nous avons affaire à une employeetable volumineuse et que nous exécutons souvent des requêtes avec des WHEREclauses qui restreignent les résultats à un pays ou un département particulier. Pour une réponse de requête plus rapide, la table Hive peut être PARTITIONED BY (country STRING, DEPT STRING). Le partitionnement des tables modifie la façon dont Hive structure le stockage des données et Hive crée désormais des sous-répertoires reflétant la structure de partitionnement comme

... / employés / pays = ABC / DEPT = XYZ .

Si la requête limite les employés à partir de country=ABC, il analysera uniquement le contenu d'un répertoire country=ABC. Cela peut considérablement améliorer les performances des requêtes, mais uniquement si le schéma de partitionnement reflète un filtrage commun. La fonctionnalité de partitionnement est très utile dans Hive, cependant, une conception qui crée trop de partitions peut optimiser certaines requêtes, mais être préjudiciable pour d'autres requêtes importantes. Un autre inconvénient est d'avoir trop de partitions est le grand nombre de fichiers et de répertoires Hadoop qui sont créés inutilement et la surcharge de NameNode car il doit conserver toutes les métadonnées du système de fichiers en mémoire.

Le regroupement est une autre technique de décomposition des ensembles de données en parties plus faciles à gérer. Par exemple, supposons qu'une table utilisant datecomme partition de niveau supérieur et employee_idcomme partition de second niveau entraîne trop de petites partitions. Au lieu de cela, si nous compartimentons la table des employés et l'utilisons employee_idcomme colonne de compartimentage, la valeur de cette colonne sera hachée par un nombre défini par l'utilisateur dans des compartiments. Les enregistrements avec le même employee_id seront toujours stockés dans le même compartiment. En supposant que le nombre de employee_idest bien supérieur au nombre de compartiments, chaque compartiment en aura plusieurs employee_id. Lors de la création de la table, vous pouvez spécifier commeCLUSTERED BY (employee_id) INTO XX BUCKETS;où XX est le nombre de seaux. Le bucketing présente plusieurs avantages. Le nombre de compartiments est fixe afin qu'il ne fluctue pas avec les données. Si deux tables sont regroupées employee_id, Hive peut créer un échantillonnage logiquement correct. Le bucketing aide également à réaliser des jointures efficaces côté carte, etc.

Navneet Kumar
la source
4
Merci Navneet. Cependant, pouvez-vous expliquer comment le compartimentage se produit avec le partitionnement? Supposons que si nous spécifions 32 buckets dans la clause CLUSED BY et que l'instruction CREATE TABLE contient également la clause Partitioning, comment les partitions et les buckets seront-ils gérés ensemble? Le nombre de partitions sera-t-il limité à 32? OU pour chaque partition, 32 buckets seront créés? Chaque bucket est-il un fichier HDFS?
sgsi
12
Une table ruche peut avoir à la fois un partitionnement et un compartimentage. En fonction de votre clause de partition, pour chaque partition aura 32 compartiments créés. Oui fichier HDFS.
Navneet Kumar le
7
@sgsi Partition est un dossier, le bucket est un fichier.
leftjoin le
12
Pour mémoire, cette réponse découle du texte de Programming Hive (O'Reilly, 2012).
ianmcook
1
J'ai trouvé ce lien utile. Il contient des informations qui ajouteront plus de valeur à cette réponse. linkedin.com/pulse/…
Alex Raj Kaliamoorthy
129

Il manque quelques détails dans les explications précédentes. Pour mieux comprendre le fonctionnement du partitionnement et du compartimentage, vous devez examiner comment les données sont stockées dans la ruche. Disons que vous avez une table

CREATE TABLE mytable ( 
         name string,
         city string,
         employee_id int ) 
PARTITIONED BY (year STRING, month STRING, day STRING) 
CLUSTERED BY (employee_id) INTO 256 BUCKETS

puis la ruche stockera les données dans une hiérarchie de répertoires comme

/user/hive/warehouse/mytable/y=2015/m=12/d=02

Donc, vous devez être prudent lors du partitionnement, car si vous partitionnez par exemple par employee_id et que vous avez des millions d'employés, vous finirez par avoir des millions de répertoires dans votre système de fichiers. Le terme « cardinalité » fait référence au nombre de valeurs possibles qu'un champ peut avoir. Par exemple, si vous avez un champ "pays", les pays du monde sont environ 300, donc la cardinalité serait d'environ 300. Pour un champ comme «timestamp_ms», qui change toutes les millisecondes, la cardinalité peut être de plusieurs milliards. En général, lorsque vous choisissez un champ pour le partitionnement, il ne devrait pas avoir une cardinalité élevée, car vous vous retrouverez avec beaucoup trop de répertoires dans votre système de fichiers.

Le clustering aka bucketing, d'autre part, se traduira par un nombre fixe de fichiers, puisque vous spécifiez le nombre de buckets. Ce que la ruche fera est de prendre le champ, de calculer un hachage et d'attribuer un enregistrement à ce compartiment. Mais que se passe-t-il si vous utilisez, disons, 256 compartiments et que le champ sur lequel vous effectuez un compartimentage a une faible cardinalité (par exemple, c'est un état américain, il ne peut donc y avoir que 50 valeurs différentes)? Vous aurez 50 buckets avec des données et 206 buckets sans données.

Quelqu'un a déjà mentionné comment les partitions peuvent réduire considérablement la quantité de données que vous interrogez. Ainsi, dans mon exemple de tableau, si vous souhaitez interroger uniquement à partir d'une certaine date, le partitionnement par année / mois / jour va réduire considérablement le montant d'E / S. Je pense que quelqu'un a également mentionné comment le bucketing peut accélérer les jointures avec d'autres tables qui ont exactement le même bucketing , donc dans mon exemple, si vous joignez deux tables sur le même employee_id, la ruche peut faire la jointure bucket par bucket (encore mieux s'ils sont déjà triés par employee_id car il va fusionner les parties qui sont déjà triées, ce qui fonctionne en temps linéaire aka O (n)).

Ainsi, le compartimentage fonctionne bien lorsque le champ a une cardinalité élevée et que les données sont uniformément réparties entre les compartiments. Le partitionnement fonctionne mieux lorsque la cardinalité du champ de partitionnement n'est pas trop élevée.

En outre, vous pouvez partitionner sur plusieurs champs , avec une commande (année / mois / jour en est un bon exemple), alors que vous ne pouvez diviser que sur un seul champ .

Roberto Congiu
la source
Pouvez-vous expliquer le comportement CLUSTERED-BY avec SORTED-BY dans un exemple? Selon mon exemple, j'ai trouvé SORTED-BY ne faisant rien. Est-ce que je manque quelque chose.
Jagadish Talluri
2
CLUSTERED BY x, y revient à écrire DISTRIBUTE BY x, y SORT BY x, y (voir cwiki.apache.org/confluence/display/Hive/… ) donc l'ajout de SORT BY à CLUSTERED BY n'a aucun effet.
Roberto Congiu
Intéressant, je suis d'accord avec l'utilisation dans la requête sélectionnée. Mais je me suis demandé pourquoi les gens utilisent clustered by et triés ensemble dans l'instruction de création de table. S'il n'y a pas de signification pour SORTED BY dans DDL, alors pourquoi ce mot clé est-il présent? Je n'ai pas compris.
Jagadish Talluri
SORTED BY est destiné à être utilisé avec DISTRIBUTED BY. Par exemple, vous souhaiterez peut-être distribuer par identifiant d'utilisateur et trier par heure dans le compartiment. CLUSTER BY est juste un raccourci pour quand la clause sur SORTED BY et DISTRIBUTED BY est la même. La seule chose à laquelle je peux penser, c'est si vous distribuez par x, y et triez par x, y et z
Roberto Congiu
Je ne suis pas sûr de ce que vous entendez par "vous ne pouvez effectuer un seau que sur un seul champ". Je pense qu'il est possible de diviser par plusieurs champs la fonction de hachage prendra simplement tous les champs et les combinera.
Istvan
18

Je pense que je suis en retard pour répondre à cette question, mais cela revient dans mon fil d'actualité.

Navneet a fourni une excellente réponse. Ajouter à cela visuellement.

Le partitionnement aide à éliminer les données, s'il est utilisé dans la clause WHERE, alors que le compartimentage aide à organiser les données de chaque partition en plusieurs fichiers, de sorte que le même ensemble de données est toujours écrit dans le même compartiment. Aide beaucoup à joindre des colonnes.

Supposons que vous ayez une table avec cinq colonnes, name, server_date, some_col3, some_col4 et some_col5. Supposons que vous ayez partitionné la table sur server_date et compartimenté sur la colonne de nom dans 10 compartiments, votre structure de fichier ressemblera à quelque chose comme ci-dessous.

  1. server_date = xyz
    • 00000_0
    • 00001_0
    • 00002_0
    • ........
    • 00010_0

Ici server_date = xyz est la partition et 000 fichiers sont les buckets dans chaque partition. Les buckets sont calculés en fonction de certaines fonctions de hachage, donc les lignes avec name = Sandy iront toujours dans le même bucket.

Priyesh
la source
2
Selon Roberto dans la réponse ci-dessus, server_date serait un mauvais exemple de partitionnement car sa valeur de cardinalité est vraiment élevée. Et donc vous finirez par avoir trop de dossiers dans hdfs.
Gaurang Shah
server_date est mentionné ici à titre d'exemple. Dans le monde réel, la partition se produit généralement comme décrit par Roberto, en décomposant la date en année / mois / jour. Voilà comment il devrait être.
Priyesh
17

Partitionnement de la ruche:

La partition divise une grande quantité de données en plusieurs tranches en fonction de la valeur d'une ou plusieurs colonnes de table.

Supposons que vous stockez des informations sur des personnes dans le monde entier réparties dans plus de 196 pays couvrant environ 500 crores d'entrées. Si vous souhaitez interroger des personnes d'un pays particulier (Cité du Vatican), en l'absence de partitionnement, vous devez scanner les 500 crores d'entrées, même pour récupérer les milliers d'entrées d'un pays. Si vous partitionnez la table en fonction du pays, vous pouvez affiner le processus de requête en vérifiant simplement les données pour une seule partition de pays. La partition Hive crée un répertoire distinct pour une valeur de colonne (s).

Avantages:

  1. Répartir la charge d'exécution horizontalement
  2. Exécution plus rapide des requêtes en cas de partition avec un faible volume de données. Par exemple, obtenir la population de la " Cité du Vatican " revient très rapidement au lieu de rechercher la population entière du monde.

Les inconvénients:

  1. Possibilité de créer trop de petites partitions - trop de répertoires.
  2. Efficace pour les données de faible volume pour une partition donnée. Mais certaines requêtes comme group by sur un volume élevé de données prennent encore du temps à s'exécuter. Par exemple, le regroupement de la population de la Chine prendra du temps par rapport au regroupement de la population de la Cité du Vatican. La partition ne résout pas le problème de réactivité en cas de biais de données vers une valeur de partition particulière.

Seau de la ruche:

Le regroupement décompose les données en parties plus gérables ou égales.

Avec le partitionnement, il est possible que vous puissiez créer plusieurs petites partitions en fonction des valeurs de colonne. Si vous optez pour le compartimentage, vous limitez le nombre de compartiments pour stocker les données. Ce numéro est défini lors des scripts de création de table.

Avantages

  1. En raison de volumes égaux de données dans chaque partition, les jointures du côté de la carte seront plus rapides.
  2. Réponse aux requêtes plus rapide comme le partitionnement

Les inconvénients

  1. Vous pouvez définir le nombre de buckets lors de la création de la table, mais le chargement d'un volume égal de données doit être effectué manuellement par les programmeurs.
Ravindra babu
la source
9

Avant d'entrer dans le vif du sujet Bucketing, nous devons comprendre ce que Partitioningc'est. Prenons le tableau ci-dessous comme exemple. Notez que je n'ai donné que 12 enregistrements dans l'exemple ci-dessous pour une compréhension de niveau débutant. Dans les scénarios en temps réel, vous pouvez avoir des millions d'enregistrements.

entrez la description de l'image ici



PARTITIONNEMENT
---------------------
Partitioning est utilisé pour obtenir des performances lors de l'interrogation des données. Par exemple, dans le tableau ci-dessus, si nous écrivons le sql ci-dessous, il doit analyser tous les enregistrements de la table, ce qui réduit les performances et augmente la surcharge.

select * from sales_table where product_id='P1'

Pour éviter une analyse complète de la table et pour lire uniquement les enregistrements associés, product_id='P1'nous pouvons partitionner (diviser les fichiers de la table de la ruche) en plusieurs fichiers en fonction de la product_idcolonne. Ainsi, le fichier de la table de la ruche sera divisé en deux fichiers l'un avec product_id='P1'et l'autre avec product_id='P2'. Maintenant, lorsque nous exécutons la requête ci-dessus, il analysera uniquement le product_id='P1'fichier.

../hive/warehouse/sales_table/product_id=P1
../hive/warehouse/sales_table/product_id=P2

La syntaxe de création de la partition est donnée ci-dessous. Notez que nous ne devons pas utiliser la product_iddéfinition de colonne avec les colonnes non partitionnées dans la syntaxe ci-dessous. Cela ne devrait être que dans la partitioned byclause.

create table sales_table(sales_id int,trans_date date, amount int) 
partitioned by (product_id varchar(10))

Inconvénients : Nous devons être très prudents lors du partitionnement. Autrement dit, il ne doit pas être utilisé pour les colonnes où le nombre de valeurs répétitives est très inférieur (en particulier les colonnes de clé primaire) car il augmente le nombre de fichiers partitionnés et augmente la surcharge pour le Name node.



BUCKETING
------------------
Bucketing est utilisé pour surmonter ce consque j'ai mentionné dans la section de partitionnement. Cela doit être utilisé lorsqu'il y a très peu de valeurs répétitives dans une colonne (exemple - colonne de clé primaire). Ceci est similaire au concept d'index sur la colonne de clé primaire dans le SGBDR. Dans notre tableau, nous pouvons prendre une Sales_Idcolonne pour le seau. Cela sera utile lorsque nous aurons besoin d'interroger la sales_idcolonne.

Vous trouverez ci-dessous la syntaxe du compartimentage.

create table sales_table(sales_id int,trans_date date, amount int) 
partitioned by (product_id varchar(10)) Clustered by(Sales_Id) into 3 buckets

Ici, nous allons diviser davantage les données en quelques fichiers supplémentaires au-dessus des partitions.

entrez la description de l'image ici

Puisque nous avons spécifié des 3buckets, il est divisé en 3 fichiers chacun pour chacun product_id. Il utilise en interne modulo operatorpour déterminer dans quel seau chacun sales_iddoit être stocké. Par exemple, pour le product_id='P1', le sales_id=1sera stocké dans le fichier 000001_0 (c'est-à-dire 1% 3 = 1), sales_id=2sera stocké dans le fichier 000002_0 (c'est-à-dire 2% 3 = 2), sales_id=3sera stocké dans le fichier 000000_0 (c'est-à-dire 3% 3 = 0) etc.

Sarath Avanavu
la source
Pour les colonnes numériques groupées, prend-il toujours simplement mod par le nombre de seaux? Pour les colonnes en cluster à valeur de chaîne, utilise-t-il le Java hashCode()de la chaîne comme fonction de hachage? Le programmeur peut-il choisir la fonction de hachage?
Don Smith
Apparemment (et d'après mes expériences) la ruche utilise une variante de la méthode hashCode () de Java: github.com/apache/hive/blob/release-1.1.0/serde/src/java/org/… . Cela a été mentionné ici: stackoverflow.com/questions/30594038/… .
Don Smith
3

La différence est que le compartimentage divise les fichiers par nom de colonne et le partitionnement divise les fichiers sous Par une valeur particulière dans la table

J'espère que je l'ai défini correctement

Uriya Harel
la source
0

Il y a de bonnes réponses ici. Je voudrais rester bref pour mémoriser la différence entre la partition et les seaux.

Vous partitionnez généralement sur une colonne moins unique. Et le regroupement sur la colonne la plus unique.

Exemple si vous considérez la population mondiale avec le pays, le nom de la personne et son identifiant bio-métrique comme exemple. Comme vous pouvez le deviner, le champ de pays serait la colonne la moins unique et l'identifiant bio-métrique serait la colonne la plus unique. Donc, idéalement, vous auriez besoin de partitionner la table par pays et de la classer par identifiant bio-métrique.

SVK
la source
-1

L'utilisation de partitions dans la table Hive est fortement recommandée pour les raisons ci-dessous -

  • L'insertion dans la table Hive devrait être plus rapide (car elle utilise plusieurs threads pour écrire des données sur des partitions)
  • La requête à partir de la table Hive doit être efficace avec une faible latence.

Exemple :-

Supposons que le fichier d'entrée (100 Go) est chargé dans temp-hive-table et qu'il contient des données bancaires provenant de différentes zones géographiques.

Table Hive sans partition

Insert into Hive table Select * from temp-hive-table

/hive-table-path/part-00000-1  (part size ~ hdfs block size)
/hive-table-path/part-00000-2
....
/hive-table-path/part-00000-n

Le problème avec cette approche est - Il analysera les données entières pour toute requête que vous exécutez sur cette table. Le temps de réponse sera élevé par rapport aux autres approches où le partitionnement et le regroupement sont utilisés.

Table Hive avec partition

Insert into Hive table partition(country) Select * from temp-hive-table

/hive-table-path/country=US/part-00000-1       (file size ~ 10 GB)
/hive-table-path/country=Canada/part-00000-2   (file size ~ 20 GB)
....
/hive-table-path/country=UK/part-00000-n       (file size ~ 5 GB)

Avantages - Ici, on peut accéder aux données plus rapidement lorsqu'il s'agit d'interroger des données pour des transactions géographiques spécifiques. Inconvénients - L'insertion / interrogation de données peut être encore améliorée en fractionnant les données au sein de chaque partition. Voir l'option de regroupement ci-dessous.

Table Hive avec partition et compartimentage

Remarque: Créez une table de ruche ..... avec "CLUSTERED BY (Partiton_Column) dans 5 buckets

Insert into Hive table partition(country) Select * from temp-hive-table

/hive-table-path/country=US/part-00000-1       (file size ~ 2 GB)
/hive-table-path/country=US/part-00000-2       (file size ~ 2 GB)
/hive-table-path/country=US/part-00000-3       (file size ~ 2 GB)
/hive-table-path/country=US/part-00000-4       (file size ~ 2 GB)
/hive-table-path/country=US/part-00000-5       (file size ~ 2 GB)

/hive-table-path/country=Canada/part-00000-1   (file size ~ 4 GB)
/hive-table-path/country=Canada/part-00000-2   (file size ~ 4 GB)
/hive-table-path/country=Canada/part-00000-3   (file size ~ 4 GB)
/hive-table-path/country=Canada/part-00000-4   (file size ~ 4 GB)
/hive-table-path/country=Canada/part-00000-5   (file size ~ 4 GB)

....
/hive-table-path/country=UK/part-00000-1       (file size ~ 1 GB)
/hive-table-path/country=UK/part-00000-2       (file size ~ 1 GB)
/hive-table-path/country=UK/part-00000-3       (file size ~ 1 GB)
/hive-table-path/country=UK/part-00000-4       (file size ~ 1 GB)
/hive-table-path/country=UK/part-00000-5       (file size ~ 1 GB)

Avantages - Insertion plus rapide. Requête plus rapide.

Inconvénients - Le regroupement créera plus de fichiers. Il peut y avoir un problème avec de nombreux petits fichiers dans certains cas spécifiques

J'espère que cela aidera !!

Ajay Ahuja
la source