Citant les Spark DataFrames, Datasets et manuel SQL :
Une poignée d'optimisations Hive n'est pas encore incluse dans Spark. Certains d'entre eux (tels que les index) sont moins importants en raison de Spark Modèle de calcul en mémoire de SQL. D'autres sont prévus pour les futures versions de Spark SQL).
Étant nouveau sur Spark, je suis un peu déconcerté par cela pour deux raisons:
Spark SQL est conçu pour traiter le Big Data, et au moins dans mon cas d'utilisation, la taille des données dépasse de loin la taille de la mémoire disponible. En supposant que ce n'est pas rare, que signifie le "modèle de calcul en mémoire de Spark SQL"? Spark SQL est-il recommandé uniquement dans les cas où les données tiennent en mémoire?
Même en supposant que les données tiennent en mémoire, une analyse complète sur un très grand ensemble de données peut prendre beaucoup de temps. J'ai lu cet argument contre l'indexation dans la base de données en mémoire, mais je n'étais pas convaincu. L'exemple décrit une analyse d'une table de 10 000 000 d'enregistrements, mais il ne s'agit pas vraiment de données volumineuses. L'analyse d'une table avec des milliards d'enregistrements peut entraîner des requêtes simples de type "SELECT x WHERE y = z" qui prennent une éternité au lieu de revenir immédiatement.
Je comprends que les index ont des inconvénients comme INSÉRER/METTRE À JOUR plus lentement, l'espace requis, etc. Mais dans mon cas d'utilisation, je traite et charge d'abord un grand lot de données dans Spark SQL, puis j'explore cela données dans leur ensemble, sans autres modifications. Spark SQL est utile pour le traitement et le chargement distribués initiaux des données, mais le manque d'indexation rend l'exploration interactive plus lente et plus lourde que je ne le pensais) être.
Je me demande alors pourquoi l'équipe Spark SQL considère les index sans importance à un point tel que cela ne correspond pas à leur feuille de route. Existe-t-il un modèle d'utilisation différent qui peut fournir les avantages de l'indexation sans recourir à l'implémentation de quelque chose équivalent indépendamment?
Indexation des données d'entrée
Indexation des structures de données distribuées :
Cela étant dit, certaines formes de structures indexées existent dans Spark écosystème. Plus particulièrement Databricks fournit Data Skipping Index sur sa plate-forme.
D'autres projets, comme Succinct (principalement inactif aujourd'hui) adoptent une approche différente et utilisent des techniques de compression avancées avec prise en charge de l'accès aléatoire.
Bien sûr, cela soulève une question - si vous avez besoin d'un accès aléatoire efficace, pourquoi ne pas utiliser un système conçu comme une base de données depuis le début. Il existe de nombreux choix, y compris au moins quelques-uns maintenus par la Fondation Apache. En même temps Spark au fur et à mesure qu'un projet évolue, et le devis que vous avez utilisé peut ne pas refléter complètement les futures directions Spark.
En général, l'utilité des index est au mieux discutable. Au lieu de cela, le partitionnement des données est plus important. Ce sont des choses très différentes, et ce n'est pas parce que votre base de données de choix prend en charge les index qu'ils ont du sens compte tenu de ce que Spark essaie de faire. Et cela n'a rien à voir avec "en mémoire" .
Alors qu'est-ce qu'un index, de toute façon?
À l'époque où le stockage permanent était extrêmement cher (au lieu d'être essentiellement gratuit), les systèmes de bases de données relationnelles visaient à minimiser l'utilisation du stockage permanent. Le modèle relationnel, par nécessité, divisait un enregistrement en plusieurs parties - normalisait les données - et les stockait à différents endroits. Pour lire un enregistrement client, vous pouvez peut-être lire une table customer
, une table customerType
, retirer quelques entrées d'une table address
, etc. Si vous aviez une solution cela vous obligeait à lire l'intégralité du tableau pour trouver ce que vous vouliez, cela est très coûteux, car vous devez numériser tant de tableaux.
Mais ce n'est pas la seule façon de faire les choses. Si vous n'avez pas besoin d'avoir des colonnes à largeur fixe, vous pouvez stocker l'ensemble complet de données en un seul endroit. Au lieu d'effectuer une analyse de table complète sur un tas de tables, vous n'avez besoin de le faire que sur une seule table. Et ce n'est pas aussi mauvais que vous le pensez, surtout si vous pouvez partitionner vos données.
40 ans plus tard, les lois de la physique ont changé. Les vitesses de lecture/écriture aléatoires du disque dur et les vitesses de lecture/écriture linéaires ont radicalement divergé. Vous pouvez essentiellement effectuer 350 mouvements de tête par seconde par disque. (Un peu plus ou moins, mais c'est un bon nombre moyen.) En revanche, un seul lecteur de disque peut lire environ 100 Mo par seconde. Qu'est-ce que ça veut dire?
Faites le calcul et réfléchissez - cela signifie si vous lisez moins de 300 Ko par déplacement de tête de disque, vous réduisez le débit de votre lecteur.
Sérieusement. Pensez-y une seconde.
Le but d'un index est de vous permettre de déplacer votre tête de disque à l'emplacement précis sur le disque que vous voulez et de simplement lire cet enregistrement - dites simplement l'enregistrement address
joint dans le cadre de votre customer
record. Et je dis, c'est inutile.
Si je concevais un index basé sur la physique moderne, il me suffirait de me rapprocher de 100 Ko environ de la donnée cible (en supposant que mes données avaient été disposées en gros morceaux - mais nous parlons ici de théorie de toute façon) . Sur la base des chiffres ci-dessus, plus de précision que cela n'est qu'un gaspillage.
Revenez maintenant à la conception de votre table normalisée. Disons qu'un enregistrement customer
est vraiment divisé en 6 lignes contenues dans 5 tables. 6 mouvements totaux de tête de disque (je suppose que l'index est mis en cache en mémoire, donc pas de mouvement de disque). Cela signifie que je peux lire 1,8 Mo d'enregistrements clients linéaires/dénormalisés et être tout aussi efficace.
Et qu'en est-il de l'historique client? Supposons que je veuille non seulement voir à quoi ressemble le client aujourd'hui - imaginez que je veux l'historique complet ou un sous-ensemble de l'historique? Multipliez tout ce qui précède par 10 ou 20 et vous obtenez l'image.
Ce qui serait mieux qu'un index serait le partitionnement des données - en s'assurant que tous les enregistrements client se retrouvent dans une seule partition. De cette façon, avec un seul déplacement de tête de disque, je peux lire l'historique complet du client. Un mouvement de tête de disque.
Dites-moi encore pourquoi vous voulez des index.
Index vs ___?
Ne vous méprenez pas - il est important de "pré-cuire" vos recherches. Mais les lois de la physique suggèrent une meilleure façon de le faire que les index traditionnels. Au lieu de stocker l'enregistrement client dans un seul emplacement et de créer un pointeur vers celui-ci - un index - pourquoi ne pas stocker l'enregistrement dans plusieurs emplacements?
N'oubliez pas que l'espace disque est essentiellement libre. Au lieu d'essayer de minimiser la quantité de stockage que nous utilisons - un artefact obsolète du modèle relationnel - utilisez simplement votre disque comme cache de recherche.
Si vous pensez que quelqu'un souhaite voir les clients répertoriés à la fois par zone géographique et par représentant commercial, faites plusieurs copies de vos enregistrements client stockées de manière à optimiser ces recherches. Comme je l'ai dit, utilisez le disque comme votre cache en mémoire. Au lieu de créer votre cache en mémoire en rassemblant des éléments disparates de données persistantes, créez vos données persistantes pour refléter votre cache en mémoire de sorte que tout ce que vous avez à faire est de le lire. En fait, ne vous embêtez même pas à essayer de le stocker en mémoire - il suffit de le lire directement sur le disque chaque fois que vous en avez besoin.
Si vous pensez que cela semble fou, considérez ceci - si vous le cachez en mémoire, vous allez probablement le mettre en cache deux fois. Il est probable que votre contrôleur de système d'exploitation/lecteur utilise la mémoire principale comme cache. Ne vous embêtez pas à mettre les données en cache car quelqu'un d'autre est déjà!
Mais je m'égare ...
Pour faire court, Spark supporte absolument le bon type d'indexation - la possibilité de créer des données dérivées complexes à partir de données brutes pour rendre les utilisations futures plus efficaces. Il ne le fait tout simplement pas de la manière vous le voulez.