La vie sans JOIN… la compréhension et les pratiques communes

Beaucoup de “BAW” (big ass-sites) utilisent des techniques de stockage et de récupération de données qui reposent sur des tables énormes avec index et utilisent des requêtes qui ne peuvent / ne peuvent pas utiliser JOIN dans leurs requêtes (BigTable, HQL, etc.) traiter les bases de données d’évolutivité et de fragmentation. Comment cela fonctionne-t-il lorsque vous avez beaucoup de données très liées?

Je ne peux que spéculer sur le fait qu’une grande partie de ce regroupement doit se faire du côté des applications, mais cela ne commence-t-il pas à coûter cher? Que faire si vous devez faire plusieurs requêtes sur plusieurs tables différentes pour obtenir des informations à comstackr? Frapper la firebase database ne commence-t-il pas à devenir plus onéreux qu’à utiliser les jointures en premier lieu? Je suppose que cela dépend de la quantité de données que vous avez?

Et pour les ORM couramment disponibles, comment ont-ils tendance à gérer l’incapacité à utiliser les jointures? Y a-t-il un support pour cela dans les ORM qui sont aujourd’hui très utilisés? Ou est-ce que la plupart des projets qui doivent s’approcher de ce niveau de données ont tendance à se défaire de toute façon?

Donc, cela ne s’applique à aucun projet en cours que je fais, mais c’est quelque chose qui est dans ma tête depuis plusieurs mois maintenant que je ne peux que spéculer sur les «meilleures pratiques». Je n’ai jamais eu besoin de résoudre ce problème dans aucun de mes projets car ils n’ont jamais atteint une échelle requirejse. Espérons que cette question aide aussi les autres.

Comme quelqu’un l’a dit ci-dessous, les ORM “ne fonctionnent pas” sans jointures. Existe-t-il d’autres couches d’access aux données déjà disponibles pour les développeurs travaillant avec des données à ce niveau?

EDIT: Pour des précisions, Vinko Vrsalovic a déclaré:

“Je pense que snicker veut parler de NO-SQL, où les données transactionnelles sont dénormalisées et utilisées dans les systèmes Hadoop ou BigTable ou Cassandra.”

C’est en effet ce dont je parle.

Points bonus pour ceux qui attrapent la référence xkcd.

À mon avis, une firebase database relationnelle est un outil général pour couvrir vos paris. Les ordinateurs modernes sont assez rapides et les SGBDR sont suffisamment bien optimisés pour que vous puissiez atteindre une taille tout à fait respectable sur un seul boîtier. En choisissant un SGBDR, vous vous accordez un access très flexible à vos données et vous avez la possibilité d’avoir de fortes contraintes d’exactitude qui facilitent le codage des données. Cependant, le SGBDR ne va pas représenter une bonne optimisation pour un problème particulier, il vous donne simplement la possibilité de modifier facilement les problèmes.

Si vous commencez à croître rapidement et que vous réalisez que vous allez devoir dépasser la taille d’un serveur de firebase database unique, vous avez soudainement des choix beaucoup plus difficiles à faire. Vous devrez commencer à identifier les goulots d’étranglement et à les supprimer. Le SGBDR sera un nœud de codage que vous devrez démêler. Plus vos données sont interconnectées, plus vous devrez travailler, mais peut-être que vous ne devrez pas démêler complètement le tout. Si vous lisez beaucoup, vous pouvez peut-être vous en sortir avec une simple réplication. Si vous saturez votre marché et que la croissance se stabilise, vous pouvez peut-être partiellement dénormaliser et diviser en un nombre fixe de serveurs de firebase database. Peut-être que vous avez juste une poignée de tables de problèmes qui peuvent être déplacées vers un magasin de données plus évolutif. Peut-être que votre profil d’utilisation est très convivial et que vous pouvez simplement migrer la charge vers un cluster memcached géant.

Lorsque des magasins de valeurs-clés évolutives, comme BigTable, sont disponibles, cela ne fonctionne pas, et vous avez tellement de données d’un seul type que même lorsqu’elles sont dénormalisées, une seule table est trop lourde pour un seul serveur. À ce stade, vous devez pouvoir le partitionner de manière arbitraire et disposer toujours d’une API propre pour y accéder. Naturellement, lorsque les données sont réparties sur un si grand nombre de machines, vous ne pouvez pas utiliser des algorithmes nécessitant que ces machines se parlent beaucoup, ce que nécessiteraient de nombreux algorithmes relationnels standard. Comme vous le suggérez, ces algorithmes d’interrogation dissortingbués ont le potentiel d’exiger une puissance de traitement supérieure à celle de JOIN dans une firebase database relationnelle correctement indexée, mais parallèlement, la performance en temps réel est bien meilleure qu’une seule machine. une machine pouvant contenir l’intégralité de l’index existe même).

Désormais, une fois que vous pouvez dimensionner vos énormes données horizontalement (en branchant simplement plus de serveurs), la partie la plus difficile de l’évolutivité est réalisée. Eh bien, je ne devrais pas dire que les opérations en cours et le développement à cette échelle sont beaucoup plus difficiles que l’application à serveur unique, mais les serveurs d’application sont généralement insignifiants via une architecture sans partage. les données dont ils ont besoin en temps opportun.

Pour répondre à votre question sur la manière dont les ORM couramment utilisés gèrent l’incapacité à utiliser JOIN, la réponse courte est qu’ils ne le font pas . ORM signifie Object Relational Mapping, et la plupart des tâches d’un ORM ne font que traduire le puissant paradigme relationnel de la logique des prédicats, des structures de données simples orientées object. La plupart de la valeur de ce qu’ils vous donnent ne sera tout simplement pas possible à partir d’un magasin de clés. En pratique, vous devrez probablement créer et maintenir votre propre couche d’access aux données adaptée à vos besoins particuliers, car les profils de données à ces échelles vont considérablement varier et je pense qu’il y a trop de compromis pour qu’un outil général émerge. et devenir dominant comme le font les SGBDR. En bref, vous devrez toujours faire plus de travail à cette échelle.

Cela dit, il sera certainement intéressant de voir quel type de fonctionnalité agrégée relationnelle ou autre peut être construite sur les primitives de magasin de valeurs-clés. Je n’ai pas assez d’expérience ici pour commenter en détail, mais il ya beaucoup de connaissances en informatique à l’échelle de l’entreprise depuis plusieurs années (par exemple, Oracle), beaucoup de connaissances théoriques inexploitées dans le monde universitaire, Google, Amazon, Facebook et autres, mais les connaissances qui ont filtré dans la communauté de développement au sens large sont encore assez limitées.

Cependant, maintenant que de nombreuses applications se déplacent sur le Web et que de plus en plus de personnes dans le monde sont en ligne, de plus en plus d’applications devront être déployées et les meilleures pratiques commenceront à se concrétiser. Les services de cloud computing, tels que AppEngine et EC2, ainsi que les bases de données open source telles que Cassandra, réduiront l’écart de connaissances des deux côtés. Dans un certain sens, cela va de pair avec un calcul parallèle et asynchrone, qui en est également à ses balbutiements. Définitivement une période fascinante pour être programmeur.

Vous commencez à partir d’une hypothèse erronée.

L’entreposage de données ne normalise pas les données de la même manière qu’une application de transaction se normalise. Il n’y a pas “beaucoup” de jointures. Il y en a relativement peu.

En particulier, les deuxième et troisième violations de la forme normale ne constituent pas un “problème”, car les entrepôts de données sont rarement mis à jour. Et quand ils sont mis à jour, il suffit généralement de changer l’indicateur de statut pour que les dimensions d’une ligne soient «actuelles» et «non actuelles».

Comme vous n’avez pas à vous soucier des mises à jour, vous ne décomposez pas les données au niveau 2NF où une mise à jour ne peut pas entraîner de relations anormales. Aucune mise à jour ne signifie aucune anomalie; et pas de décomposition et pas de jointures. Vous pouvez pré-joindre tout.

Généralement, les données DW sont décomposées selon un schéma en écanvas. Cela vous guide pour décomposer les données en tables “fact” numériques contenant les mesures – nombres avec unités – et les références de clé étrangère à la dimension.

Une dimension (ou «entité commerciale») est considérée comme une chose réelle avec des atsortingbuts. Cela inclut souvent des choses comme la géographie, l’heure, le produit, le client, etc. Ces éléments ont souvent des hiérarchies complexes. Les hiérarchies sont généralement arbitraires, définies par divers besoins de reporting métier et non modélisées sous la forme de tables séparées, mais simplement par des colonnes dans la dimension utilisée pour l’agrégation.


Pour répondre à certaines de vos questions.

“Ce rapprochement doit être fait du côté des applications”. Genre de. Les données sont “pré-jointes” avant d’être chargées. Les données de dimension sont souvent une jointure de données source pertinentes sur cette dimension. Il est joint et chargé comme une structure relativement plate.

Il n’est pas mis à jour Au lieu de mises à jour, des enregistrements historiques supplémentaires sont insérés.

“mais ça ne commence pas à coûter cher?”. Genre de. Il faut un peu de soin pour charger les données. Cependant, il n’y a pas beaucoup de jointures de rapports / parsings. Les données sont pré-jointes.

Les problèmes ORM sont largement discutables car les données sont pré-jointes. Votre ORM correspond au fait ou à la dimension, le cas échéant. Sauf dans des cas particuliers, les dimensions ont tendance à être petites et correspondent entièrement à la mémoire. L’exception est lorsque vous êtes dans la finance (banque ou assurance) ou les services publics et que vous avez des bases de données client massives. Cette dimension client correspond rarement à la mémoire.

Un JOIN est un terme relationnel pur et toutes les bases de données ne sont pas relationnelles.

D’autres modèles de firebase database ont d’autres moyens de créer des relations.

Les bases de données réseau utilisent les chaînes infinies de find a key - fetch the reference - find a key qui doit être programmée avec un langage de programmation commun.

Le code peut être exécuté côté application ou côté serveur, mais ce n’est pas SQL et même pas basé sur les ensembles.

Si elle est conçue correctement, une firebase database réseau peut être beaucoup plus rapide qu’une firebase database relationnelle.

Par exemple, une firebase database réseau peut stocker une référence à une autre entité en tant que pointeur direct sur un décalage dans un fichier ou même sur un disque sur lequel les informations concernant cette entité sont stockées.

Cela rend la traversée des réseaux plus rapide – si vous avez écrit un code efficace pour le faire.

Une firebase database relationnelle peut uniquement stocker des références sous forme de paires de valeurs de base telles que des entiers (ou des sortingplets ou des tuples d’ordre supérieur).

Pour trouver ces valeurs dans la firebase database relationnelle, le moteur doit faire les choses suivantes:

  • Découvrez où se trouve le tuple contenant la première valeur
  • Trouvez la deuxième valeur
  • Trouver l’adresse de la racine dans un B-Tree contenant les données auxquelles le deuxième numéro fait référence
  • Traversez cet arbre
  • Recherchez le pointeur sur la table réelle (qui peut être stockée sous la forme d’un B-Tree même, auquel cas le pointeur correspond à la valeur de la PRIMARY KEY de la ligne que nous recherchons)
  • Trouver la ligne de la table par le pointeur ou traverser la table
  • Enfin, obtenez le résultat.

Et vous ne pouvez contrôler cela que dans une certaine mesure. Après cela, vous lancez simplement la requête SQL et attendez.

Modèle relationnel conçu pour simplifier la vie du développeur, pour ne pas toujours atteindre la super vitesse, peu importe quoi.

C’est la même chose que l’assemblage par rapport aux langages de niveau supérieur, le modèle relationnel étant un langage de niveau supérieur.

Vous voudrez peut-être lire l’article sur mon blog

  • Qu’est-ce qu’une firebase database relationnelle?

, dans lequel j’essaie d’expliquer les différences entre plusieurs modèles de bases de données couramment utilisés.

Lorsque vous dénormalisez vos données de cette manière, vous le faites pour éviter les coûts liés à la liaison d’éléments disparates. vous acceptez que certaines données puissent être dupliquées et que certaines manières de les combiner peuvent s’avérer difficiles, pour des raisons de performances liées à l’utilisation de requêtes simples.

Si vous devez vous joindre au niveau de l’application, cela signifie que vous ne l’avez pas suffisamment dénormalisé.

Idéalement, vous pourrez effectuer une requête pour n’importe quel jeu de données. En pratique, vous ne devriez pas avoir à utiliser plus de deux ou trois requêtes pour n’importe quel aspect de votre application, et toute jointure au niveau de l’application sera plus une récupération sortingviale des éléments des jeux de résultats séparés pour l’insertion dans la vue.

Ce genre de chose n’est vraiment nécessaire que pour des ensembles de données vraiment massifs, et toutes sortes de compromis sont nécessaires. Pour ne donner qu’un exemple: BigTable ne peut pas faire de requêtes agrégées, telles que vous donner un compte. Il peut être utilisé pour vous donner un chiffre à peu près exact – en ce sens que si vous avez, par exemple, 12 149 173 dossiers dont 23 721 ont été ajoutés au cours de la dernière heure, peu importe que vous trouviez le meilleur vous avez “environ 12 100 000 enregistrements”. Si votre application dépend de la connaissance du chiffre précis à un moment donné, vous ne devriez pas utiliser BigTable pour cela, c’est l’attitude générale.

Les applications comme Facebook ont ​​très peu de modifications de données, la plupart du temps, les utilisateurs publient de nouveaux éléments. Donc, le fait que les enregistrements multiples doivent être mis à jour lorsqu’un élément est modifié est un problème moindre.

Cela permet de ne pas normaliser les données sans heurter les problèmes courants liés aux mises à jour.

Les applications telles qu’Amazon peuvent se permettre de charger toutes les données d’un seul utilisateur dans la RAM (quelle est la taille d’un panier après tout?), Puis mettre à jour les données dans la RAM et les écrire en un seul élément de données.

Supprimant à nouveau le besoin de normaliser la plupart des données.

Vous traitez la mise à l’échelle pour faciliter le développement d’applications. Si vous n’avez pas besoin d’évoluer vers de grands sumts, vous souhaiterez peut-être conserver la facilité de développement des applications que le SGBDR fournit.

Je pense que dans ces situations, vous allez être tout à fait seul et allez devoir tout faire vous-même. Je n’y suis pas allé mais je l’ai considéré pour certains de nos projets. Vous pouvez devenir assez gros avec les bases de données relationnelles (comme le démontre SO), alors je continuerai à profiter de la qualité relationnelle pour le moment.

Généralement, l’entreposage de données repose sur l’utilisation de jointures et de données divisées en dimensions et en tables de faits (avec ce que l’on appelle les “schémas en écanvas”, etc.)

Les jointures seront souvent pré-calculées et stockées sous la forme de tables dé-normalisées.

Je ne connais aucun outil ORM fonctionnant avec des systèmes de firebase database qui n’autorisent pas les jointures, car ceux-ci ne sont généralement pas considérés comme des bases de données relationnelles traditionnelles.