Stockage HDFS et Hive - comparaison des formats de fichiers et compressions
By WORMS David
13 mars 2012
- Catégories
- Data Engineering
- Tags
- Business Intelligence
- Hive
- ORC
- Parquet
- Format de fichier [plus][moins]
Ne ratez pas nos articles sur l'open source, le big data et les systèmes distribués, fréquence faible d’un email tous les deux mois.
Il y a quelques jours, nous avons conduit un test dans le but de comparer différents format de fichiers et méthodes de compression disponibles dans Hive. Parmi ces formats, certains sont natifs à HDFS et s’appliquent à tous les utilisateurs d’Hadoop. La suite de tests est composée de requête Hive toutes similaires qui créent une table, éventuellement définissent une méthode de compression et chargent un jeu de données dans cette table nouvellement créée. Parmi les requêtes écrites sont testés les formats “sequence file”, “text file” et “RCFILE” ainsi que les codecs de compression “default”, “bz”, “gz”, “LZO” et “Snappy”.
N.B., cet article est la traduction d’un article précédent publié en anglais en mars dernier. Sa traduction est justifiée par la popularité de celui-ci.
Mise à jour, le 4 avril 2012 : réponse au commentaire de Huchev relatif au codec LZ4.
Mise en place
L’environnement sur lequel ont été lancés ces tests est un cluster de 20 noeuds comprenant 120 To de stockage et fonctionnant sous Cloudera CDH3U3. Le jeu de données original est un répertoire de 1.33 Go composé de 80 fichiers non divisibles compressés en “bz2”. Les données à l’intérieur sont structurées au format CSV pour un total de 125.000.000 lignes.
Ci-dessous, voici un exemple de requête Hive qui importe les données en utilisant le format “RCFILE” et le codec de compression “LZO”.
-- Prepare
CREATE TABLE rc_lzo (
client BIGINT, ctime INT, mtime INT,
code STRING, value_1 INT, value_2 INT
) STORED AS RCFILE;
-- Compression
SET hive.exec.compress.output=true;
SET mapred.output.compression.codec=com.hadoop.compression.lzo.LzoCodec;
-- Import
INSERT OVERWRITE TABLE rc_lzo
SELECT * FROM (
SELECT
client, round(ctime / 1000), round(mtime / 1000),
code, value_1, value_2
FROM staging
) T;
Résultats
Le tableau ci-dessous rapporte les résultats obtenus. La colonne intitulée “query” décrit le type de requête testée. Le nom commence par le format de fichier et est suivi par le type de compression. Les types de compression “block” et “record” sont rapportés pour le format “sequence file” et le codec de compression par défaut.
La famille de requêtes “serdesf” correspond à un mode de sérialisation SerDe que nous avons créé sur mesure et qui encode chacune des colonnes de notre jeu de données dans un format binaire aussi approprié que possible. Dans notre cas, le champ code
peut être stocké comme un caractère (soit 1 byte), le champ value_2
peut être stocké comme la différence entre sa valeur réelle et celle du champs value_1
(soit 2 bytes). Au total, une ligne est stockée sous 16 bytes contre 65 bytes à l’origine.
Les requêtes “bss” utilisent la sérialisation BinarySortableSerDe
qui est un Hive SerDe personnalisé et qui s’associe au format “sequence file”.
La famille de requêtes “b64” utilise le paquet “base64” présent dans les contributions de Hive.
query | time | size |
---|---|---|
sf | 2mn 3s | 7.91 Go |
sf_string | 2mn 22s | 8.72 Go |
sf_df_block | 2mn 17s | 8.72 Go |
sf_df_record | 2mn 12s | 7.32 Go |
sf_bz | 2h 43mn 24s | 9.9 Go |
sf_gz | 2mn 29s | 8.72 Go |
sf_lzo | 2mn 36s | 8.80 Go |
sf_snappy | 3mn 55s | 8.23 Go |
tf | 1mn 45s | 6.44 Go |
tf_bz | 2mn 14s | 1.12 Go |
tf_df | 2mn 16s | 1.12 Go |
tf_gz | 48s | 1.34 Go |
tf_lzo | 1mn 28s | 2.41 Go |
tf_snappy | 1mn 2s | 2.55 Go |
rc | 1mn 30s | 5.78 Go |
rc_df | 5mn 15s | 917.68 Mo |
rc_gz | 4mn 36s | 917.80 Mo |
rc_snappy | 52s | 1.85 Go |
rc_lzo | 38s | 1.67 Go |
serdesf | 59s | 3.63 Go |
serdesf_df | 1mn 27s | 4.61 Go |
serdesf_bz | 3h 6mn 9s | 9.63 Go |
serdesf_gz | 1mn 51s | 6.02 Go |
serdesf_snappy | 1mn 35s | 4.80 Go |
bss | 1mn 25s | 5.73 Go |
b64 | 2mn 5s | 9.17 Go |
b64_bz | 21mn 15s | 1.14 Go |
b64_df | 21mn 25s | 1.14 Go |
b64_gz | 53s | 1.62 Go |
b64_snappy | 59s | 2.89 Go |
Quelques notes
Nous souhaitions faire tourner ces tests sur un jeu de données plus conséquent avec une structure de données plus classique mais les ressources serveurs furent très limitées à cet instant. Au final, les tailles finales des fichiers sont sans doutes représentatives mais les résultats sur les temps de création doivent être interprétés avec plus de précaution.
Les vitesses mesurées reflètent le temps nécessaire à l’importation des données seulement (avec une structure des données en entrée pas trop standard) et non comment ces formats se comportent avec des tâches map/reduce.
Nous avons aussi testé le type de représentation block
contre d’autres types de codec et nous avons pu conclure que cela n’avait aucun effet et que celui-ci n’appliquait que pour des fichiers de type “sequence file”.
Finalement, nous avons essayé de faire tourner les tests serdesf
en utilisant le format RCFILE
au lieu de sequence file
mais les résultats sont identiques à ceux de la famille de requêtes rc
.
Interprétation
La requête “tf” peut être considérée comme une référence dans la mesure où le stockage est celui d’un format CSV non compressé. Il nous fut très étrange de constater que toutes les requêtes “sequence file” ont généré des fichiers plus larges que leurs amies les “Text file”. Voilà un fait que nous n’avions pas anticipé et peut-être est-ce dû à l’utilisation intensive du type “integer”.
Pour ce qui est de la taille des fichiers, le format “RCFILE” associé à la compression par défault et “gz” ont obtenu les meilleurs résultats. Le “base64” SerDe utilisant le “sequence file” avec les compressions “bz” et “default” ne sont pas si loin de ces résultats. Les résultats “base64” sont suffisamment lents pour être mis de côté.
En terme de vitesse, les formats “RCFILE” avec les compressions “lzo” et “snappy” sont très rapides tout en préservant de forts taux de compression.
A propos LZ4
Nous n’avons pas testé la compression LZ4. Le support pour LZ4 vise les versions 0.23.1 et 0.24.0 d’Hadoop et n’est pas implémenté pour notre Cloudera CDH3U3. Si vous êtes sérieusement intéressé par LZ4, je vous invite à lire l’article comparant LZ4 avec Snappy. Cet article comparant les compressions les plus rapides en mémoire est aussi intéressant. Les 2 articles précédemment cités sont en anglais.