Hadoop comprend des produits qui peuvent fonctionner avec des fichiers de différents formats. J'ai cherché, lu et réfléchi à plusieurs reprises sur le meilleur format. Quand je suis tombé sur le format ORC de manière relativement aléatoire, je me suis intéressé, j'ai lu (et même un peu choyé), et c'est ce que j'ai compris - il est incorrect de comparer les formats en tant que tels. Plus précisément, ils sont généralement comparés, à mon avis, de manière incorrecte. En fait, un article à ce sujet, ainsi que sur le format Apache ORC (en termes techniques) et les opportunités qu'il offre.
Je vais commencer par la question: quelle peut être la taille d'une table relationnelle (en octets et très approximativement), composée de 10 000 lignes (deux champs entiers par ligne)? Habituellement, ils mettent un kat ici, et la réponse est placée sous le kat - je répondrai ici: 628 octets. Et les détails et l'histoire seront transférés sous cat.
Comment tout a commencé: j'ai construit une bibliothèque pour travailler avec Apache ORC (voir la page d'accueil du projet - https://orc.apache.org ) et compilé leur propre exemple d'écriture dans ORC (pour vous casser la tête - nous commençons par ce qui fonctionne) , il contenait 2 champs et 10 000 lignes. Je l'ai commencé - j'ai reçu le fichier orc, parce que je l'ai fait quelque part en dehors du bureau - juste au cas où, j'ai réécrit la bibliothèque et le fichier sur un lecteur flash (pressé - je n'ai pas regardé la taille, je pense que le lecteur flash peut le gérer).
Mais en quelque sorte j'ai rapidement correspondu ... J'ai regardé la taille - 628 octets. J'ai pensé que c'était une erreur, je me suis assis et j'ai commencé à comprendre. J'ai lancé l'utilitaire pour visualiser ORC à partir de la même bibliothèque compilée - le contenu du fichier montre que tout est honnête - 10 000 lignes. Après cela, je me suis demandé comment 10 000 lignes pouvaient tenir dans 628 octets (je connaissais déjà un peu ORC à ce moment-là et j'ai réalisé qu'il y avait aussi des métadonnées - le format était autosuffisant). Compris, partagez.

Je ne répéterai pas ici des mots généraux sur le format - voir le lien ci-dessus, il est bien écrit là-bas. Je vais me concentrer sur deux adjectifs en excellente forme de l'image ci-dessus (la photo est tirée de la page d'accueil du projet): essayons de comprendre pourquoi ORC est "le plus rapide" et "le plus compact".
La vitesse
La vitesse peut être différente, en ce qui concerne les données - au moins la vitesse de lecture ou d'écriture (vous pouvez aller plus loin, mais arrêtons pour l'instant). Puisque Hadoop est explicitement mentionné dans le slogan ci-dessus, nous considérerons principalement la vitesse de lecture.
Pour citer un peu plus de la documentation ORC:
Il est optimisé pour les grandes lectures en continu, mais avec un support intégré pour trouver rapidement les lignes requises. Le stockage des données dans un format en colonnes permet au lecteur de lire, décompresser et traiter uniquement les valeurs requises pour la requête en cours.
Je vais traduire un peu:
- format optimisé pour la lecture en continu de gros volumes
- contient en même temps un support pour la recherche rapide des lignes nécessaires
- vous permet de lire uniquement les données dont vous avez besoin
La taille
Il n'y avait pas de citation, je dirai avec mes propres mots
- format stocke de manière optimale les méta-informations
- trouver un équilibre entre la vitesse de lecture en continu et le stockage compact
- prise en charge intégrée pour le stockage le plus compact des valeurs de colonne
Offrir des opportunités
Je veux attirer votre attention sur le libellé des citations ci-dessus: "optimisé pour ...", "contient un support ...", "vous permet de lire ..." - le format de fichier, en tant que langage de programmation, est un moyen (dans ce cas, fournir stockage efficace et accès aux données). L'efficacité du stockage et de l'accès aux données dépend non seulement de l'outil, mais aussi de qui l'utilise et comment.
Voyons quel format le format offre pour la vitesse et la compacité.
Rangement de colonne et bande
Les données de l'ORC sont stockées sous forme de colonnes, tout d'abord elles affectent la taille. Pour assurer la vitesse de lecture en continu, le fichier est divisé en ce que l'on appelle des "bandes", chaque bande est autosuffisante, c'est-à-dire peut être lu séparément (et, par conséquent, en parallèle). En raison des bandes, la taille du fichier augmentera (les valeurs de colonne non uniques seront stockées plusieurs fois - dans les bandes où ces valeurs se produisent) - le même équilibre de "vitesse - taille" (c'est un compromis).
Indices
Le format ORC implique des index qui vous permettent de déterminer si la bande (ou plutôt, les parties de bande de 10 000 lignes chacune, le soi-disant "groupe de lignes") contient les données souhaitées ou non. Les index sont construits sur chacune des colonnes. Cela affecte la vitesse de lecture et augmente la taille. Lors de la lecture en continu d'index de lecture, d'ailleurs, vous ne pouvez pas lire.
La compression
Toutes les métadonnées sont stockées sous forme compressée, et cela
- informations statistiques et descriptives (le format vous permet de recréer la table qui y est stockée, y compris les noms et types de champs)
- indices
- informations de partitionnement (en bandes et en flux)
(ci-dessous, nous verrons que les métadonnées sont une partie essentielle du fichier)
Les valeurs des colonnes sont également stockées sous forme compressée. Dans le même temps, il est possible de lire et de décompresser uniquement le bloc de données nécessaire (c'est-à-dire qu'aucun fichier n'est compressé et pas une bande entière). La compression affecte à la fois la taille et la vitesse de lecture.
Codage
Les valeurs des colonnes - et le fichier stocke exactement ces valeurs - sont stockées sous forme codée. Dans la version actuelle du format (ORC v1) pour les entiers, par exemple, 4 options d'encodage sont disponibles. En même temps, la colonne entière n'est pas codée, des parties de la colonne sont codées, chaque partie peut être codée de manière optimale pour cette partie (ces parties sont appelées "exécuter" dans la spécification). Ainsi, la minimisation de la longueur totale des données stockées est obtenue. Encore une fois, l'effet sur la taille et la vitesse.
Voyons le fichier ORC
Regardons très brièvement ce qui se trouve à l'intérieur du fichier ORC (celui-ci fait 628 octets). Pour ceux qui ne sont pas très intéressés par les détails techniques, faites défiler jusqu'à la section suivante (sur la comparaison des formats).
Voici comment notre table a été définie dans l'exemple d'enregistrement dans ORC:

Informations sur les longueurs (je donne des captures d'écran du cahier jupyter, je pense que c'est assez clair)

Ce que nous voyons ici:
- dans la "tige" (et c'est Postscript + Footer + Metadata) seulement 1 + 23 + 115 + 50 = 189 octets
- sur une seule bande, seulement 3 + 436 = 439 octets, total 628 octets
- la bande contient un index (73 octets), des données (276 octets), un pied de page (87 octets)
Faisons attention ici au rapport du volume de données et des métadonnées (276 à 352 octets). Mais ces 276 octets de données ne sont pas seulement des données, les données contiennent un peu de «superflu» (ici pour des raisons de brièveté, je ne donne pas de captures d'écran - c'est long avec elles, je ne gérerai qu'avec mes commentaires), qui est inclus dans les données:
- PRESENT flux pour chaque colonne, il y en a trois (y compris une structure de pseudo-colonne commune) - 20 octets par chacun, total 60 octets
- flux de données (ici la pseudo-colonne n'est pas représentée) - 103 et 113 octets (colonnes "x" et "y", respectivement)
Les flux PRESENT sont des chaînes de bits qui vous permettent de savoir où les colonnes sont NULL. Pour notre exemple, leur présence semble étrange (dans les statistiques de notre fichier, il est clairement écrit qu'il n'y a pas de NULL dans les données - pourquoi alors inclure PRESENT? Cela semble être un défaut ...)
Au total, les données elles-mêmes occupent 216 octets, les métadonnées - 352.
Il ressort également des métadonnées que les deux colonnes sont codées à l'aide de la méthode DIRECT_V2 (pour les entiers, elle permet 4 types de représentations, je me réfère à la spécification pour plus de détails - c'est sur le site web du projet).
Les données
Voyons (encore une fois sans captures d'écran pour plus de brièveté) comment 10 000 nombres tiennent dans 103 octets (pour la colonne "x"):
- le codage delta est utilisé, dans lequel les paramètres sont la valeur initiale et le pas (un peu simplifié par souci de concision)
- nous avons toujours 1 étape, la valeur initiale pour la première exécution est 0, puis 511, 1022, etc.
- run (un ensemble de données codées d'une seule manière) contient dans notre cas 511 valeurs (la valeur maximale possible pour le codage delta)
- la longueur de chaque exécution dans le fichier est de 4 à 6 octets (la longueur de l'exécution augmente du fait que la valeur initiale est représentée en zigzag)
- total pour la colonne "x" nous obtenons dans le fichier 20 run-s avec une longueur totale de 103 octets (j'ai vérifié - tout s'emboîte)
Pour conclure l'examen de la présentation de notre simple tableau dans un fichier, je dirai que les indices dans cet exemple sont dégénérés - ils indiquent le début du flux de données. Je traiterai les index à l'aide d'exemples concrets; je les décrirai probablement dans un article séparé.
Pour les intéressés: sous le lien vous trouverez le cahier jupyter, dans lequel j'ai "compris" le format interne. Vous pouvez l'utiliser et répéter (le fichier ORC y est également joint).
Je suis sûr que de nombreux lecteurs sont "perdus" - oui, le format ORC n'est pas simple (à la fois en termes de compréhension des détails et en termes d'utilisation des fonctionnalités fournies).
Passons maintenant au point principal - comparaison de format incorrecte.
Fréquence de comparaison des formats: comparons la taille des fichiers aux formats A et B, la vitesse de lecture (différents types de lecture - aléatoire, streaming, etc.) aux formats A et B. Comparé, nous avons conclu que le format A est meilleur que le format B.
En utilisant l'exemple du dernier des outils de compacité (encodage) énumérés ci-dessus: les données peuvent-elles être encodées de manière optimale dans l'ORC? Oui, il existe des opportunités - voir ci-dessus. Mais tout aussi bien, vous ne pouvez pas faire ça! Cela dépend de «l'écrivain» (écrivain dans la terminologie ORC): dans l'exemple ci-dessus, l'écrivain pourrait le faire. Mais il pourrait simplement écrire 2 fois en 10 000 nombres et ce serait également correct en termes de format. En comparant les formats "par taille", nous comparons non seulement et pas tant les formats que la qualité algorithmique des systèmes d'application utilisant ces formats .
Qui est "l'écrivain" dans Hadoop? Il y en a beaucoup - par exemple, Hive, qui crée une table qui stocke ses données dans des fichiers au format ORC. En comparant, par exemple, ORC avec Parquet dans Hadoop, nous évaluons en fait la qualité de mise en œuvre de l'algorithme de conversion de données implémenté dans Hive. Nous ne comparons pas les formats (en tant que tels).
Caractéristique importante de Hadoop
Dans le monde relationnel classique, nous n'avions aucun moyen d'influencer la taille de la table dans Oracle - elle était en quelque sorte stockée et seul Oracle savait comment. Dans Hadoop, la situation est légèrement différente: nous pouvons voir comment telle ou telle table est stockée (dans quelle mesure Hive, par exemple, a réussi à la «coder»). Et, si nous voyons que cela peut être amélioré, nous avons une réelle opportunité pour cela: créer notre propre fichier ORC plus optimal et le donner à Hive en tant que table externe.
Comparer ORC et QVD
J'ai récemment décrit le format QVD que QlikVew / QlikSense utilise activement. Illustrons très brièvement ces deux formats en termes de capacités qu’ils offrent pour atteindre une vitesse de lecture maximale et minimiser la taille. Les capacités d'ORC sont décrites ci-dessus, comme dans QVD:
Stockage sur colonne
QVD peut être considéré comme un format «en colonnes», il n'y a pas de duplication des valeurs des colonnes - des valeurs uniques sont stockées une fois. MAIS il ne permet pas le traitement parallèle - vous devez d'abord lire entièrement les valeurs de toutes les colonnes, puis vous pouvez lire les lignes en parallèle.
Et il y a duplication au niveau des lignes - les lignes stockent des valeurs d'index en double dans une table de caractères.
La compression
Je n'ai pas rencontré de fichiers QVD compressés - je n'ai pas réussi - il y a une telle balise dans les métadonnées, peut-être que chacune des parties sur lesquelles il y a un décalage et une longueur dans les métadonnées (et c'est chaque table de caractères et la table de chaînes entière) peut être compressée. Dans ce cas, une lecture parallèle des lignes est "au revoir" ...
Indices
Il n'y a aucun moyen de comprendre dans le fichier QVD quelle partie de celui-ci doit être lue. En pratique, vous devez analyser la table des caractères octet par octet (chacun!), Pas très efficace ...
Codage
Le codage dans QVD n'est pas utilisé, il est possible de faire une analogie de l'index binaire dans une table de chaînes avec codage, mais cette analogie est "compensée" par la duplication des nombres par des chaînes dans les tables de caractères (pour plus de détails, consultez brièvement l'article - la valeur de la colonne est souvent représentée par le nombre ET la chaîne).
La conclusion de cette brève comparaison que j'ai personnellement formulée est la suivante: le format QVD ne contient pratiquement pas de capacités permettant un stockage compact et une lecture rapide des données contenues dans des fichiers de ce format.
(Cela semblait quelque peu offensant pour QVD, j'ajouterai un peu - le format a été créé il y a longtemps, seul QlikView / QlikSense est utilisé, et ils "stockent" toutes les données en mémoire. Je pense que le fichier QVD est simplement lu tout "tel quel" en mémoire, puis ces merveilleux produits BI à tous égards fonctionnent très rapidement avec cette présentation - les voilà maîtres ...)
Au lieu d'une conclusion
Il a critiqué et n'a encore rien offert ... - Je suggère.
Il me semble que les formats doivent être comparés non pas par l'exemple de leur implémentation spécifique, les formats doivent être comparés en termes des outils qui y sont inclus et de la capacité à utiliser ces outils pour résoudre nos problèmes spécifiques. La vitesse des processeurs est en constante augmentation, maintenant nous pouvons nous permettre presque tous les algorithmes de conversion de données après leur lecture - de toute façon, la lecture à partir du disque sera plus lente. C'est pourquoi les "moyens expressifs" des formats sont importants.
Ci-dessus, j'ai brièvement énuméré, à mon avis, les possibilités intéressantes du format ORC. Je n'ai toujours pas de statistiques sur la façon dont les choses sont dans la pratique (lesquelles de ces fonctionnalités et dans quelle mesure sont utilisées par Hive, par exemple). Quand il apparaît - j'écrirai. Les plans immédiats sont de faire un examen similaire d'un autre format de stockage populaire - Parquet.
Eh bien - et en conclusion - dans le monde moderne, il y a beaucoup d'informations, malheureusement, une partie de ces informations est trop superficielle. Nous ne céderons pas, nous regarderons l'essence.