web-dev-qa-db-fra.com

elasticsearch v.s. MongoDB pour l'application de filtrage

Cette question concerne le choix d'un choix architectural avant d'approfondir les détails de l'expérimentation et de la mise en œuvre. Il s'agit de l'adéquation, de l'évolutivité et des performances de elasticsearch v.s. MongoDB, dans un but assez spécifique.

De manière hypothétique, les deux stockent des objets de données contenant des champs et des valeurs et permettent d’interroger ce corps d’objets. Par conséquent, filtrer les sous-ensembles d'objets en fonction des champs sélectionnés ad-hoc est tout à fait approprié.

Mon application s'articulera autour de la sélection d'objets en fonction de critères. Il sélectionnerait des objets en filtrant simultanément par plus d'un champ, autrement dit, ses critères de filtrage des requêtes comprendraient généralement entre 1 et 5 champs, voire davantage dans certains cas. Tandis que les champs choisis comme filtres seraient un sous-ensemble d’un nombre beaucoup plus grand de champs. Imaginez une vingtaine de noms de champs existants et chaque requête tente de filtrer les objets en fonction de quelques champs (sur un total de 20 champs) (il peut y avoir moins de 20 noms de champs globaux existants. champs aux champs utilisés comme filtres dans chaque requête discrète). Le filtrage peut se faire par l’existence des champs choisis, ainsi que par les valeurs de champs, par ex. filtrer les objets qui ont le champ A, et leur champ B est compris entre x et y, et leur champ C est égal à w.

Mon application effectuera continuellement ce type de filtrage, alors qu’il n’y aurait rien ou très peu de constante quant aux champs utilisés pour le filtrage à tout moment. Il est peut-être nécessaire de définir les index dans elasticsearch, mais peut-être que même sans index, la vitesse est égale à celle de MongoDB.

Selon les données entrant dans le magasin, il n’ya pas de détails particuliers à ce sujet. Les objets ne seraient presque jamais changés après avoir été insérés. Peut-être faudrait-il supprimer les anciens objets; j'aimerais supposer que les deux magasins de données prennent en charge la suppression d'éléments supprimés en interne ou par une requête créée par l'application. (Moins fréquemment, les objets qui correspondent à une requête doivent également être supprimés).

Qu'est-ce que tu penses? Et avez-vous expérimenté cet aspect?

Je m'intéresse aux performances et à l'évolutivité de chacun des deux magasins de données, pour ce type de tâche. C’est le genre de question de conception architecturale, et les détails des options spécifiques au magasin ou des pierres angulaires de la requête qui devraient le rendre bien architecturé sont les bienvenus comme démonstration d’une suggestion bien pensée.

Merci!

155
matanster

Tout d’abord, il ya une distinction importante à faire ici: MongoDB est une base de données à usage général, Elasticsearch est un moteur de recherche de texte distribué soutenu par Lucene. Les gens ont parlé d’utiliser Elasticsearch comme base de données à usage général, mais ils savent que ce n’était pas sa conception originale. Je pense que les bases de données NoSQL et les moteurs de recherche à usage général vont être consolidés, mais dans l’état actuel des choses, ils proviennent de deux camps très différents.

Nous utilisons à la fois MongoDB et Elasticsearch dans mon entreprise. Nous stockons nos données dans MongoDB et utilisons Elasticsearch exclusivement pour ses fonctionnalités de recherche de texte intégral. Nous envoyons uniquement un sous-ensemble des champs de données Mongo que nous devons interroger avec élastique. Notre cas d'utilisation diffère du vôtre en ce que nos données Mongo changent constamment: un enregistrement ou un sous-ensemble des champs d'un enregistrement peut être mis à jour plusieurs fois par jour, ce qui peut nécessiter une réindexation de cet enregistrement en élastique. Pour cette seule raison, utiliser élastique comme seul magasin de données n'est pas une bonne option pour nous, car nous ne pouvons pas mettre à jour des champs sélectionnés. nous aurions besoin de réindexer un document dans son intégralité. Ce n'est pas une limitation élastique, c'est comme ça que Lucene fonctionne, le moteur de recherche sous-jacent derrière élastique. Dans votre cas, le fait que les enregistrements ne soient pas modifiés une fois stockés vous évite de devoir faire ce choix. Cela dit, si la sécurité des données est une préoccupation, je réfléchirais à deux fois avant d’utiliser Elasticsearch en tant que seul mécanisme de stockage de vos données. Cela peut arriver à un moment donné, mais je ne suis pas sûr que ce soit là.

En termes de rapidité, non seulement Elastic/Lucene est à égalité avec la vitesse d’interrogation de Mongo, mais dans votre cas, il existe "très peu de constante quant aux champs utilisés pour le filtrage à tout moment", il peut s'agir de commandes de magnitude plus rapidement, en particulier lorsque les jeux de données deviennent plus grands. La différence réside dans les implémentations de requêtes sous-jacentes:

  • Elastic/Lucene utilise les modèle d’espace vectoriel et index inversés pour recherche d’informations , qui constituent un moyen très efficace de comparer la similarité d’enregistrements à une requête. Lorsque vous interrogez Elastic/Lucene, il connaît déjà la réponse. l'essentiel de son travail consiste à classer les résultats pour vous par les plus susceptibles de correspondre aux termes de votre requête. C'est un point important: les moteurs de recherche, contrairement aux bases de données, ne peuvent pas vous garantir des résultats exacts; ils classent les résultats en fonction de leur proximité avec votre requête. Il se trouve que la plupart du temps, les résultats sont presque exacts.
  • L'approche de Mongo est celle d'un magasin de données à usage plus général; il compare les documents JSON les uns aux autres. Vous pouvez obtenir d'excellentes performances par tous les moyens, mais vous devez soigneusement élaborer vos index pour qu'ils correspondent aux requêtes que vous allez exécuter. En particulier, si vous devez interroger plusieurs champs, vous devez soigneusement définir votre clés composées , de manière à réduire autant que possible le jeu de données qui sera interrogé. Par exemple. votre première clé devrait filtrer la majorité de votre ensemble de données, votre seconde devrait filtrer davantage ce qui reste, et ainsi de suite. Si vos requêtes ne correspondent pas aux clés et à l'ordre de ces clés dans les index définis, vos performances chuteront un peu. D'autre part, Mongo est une véritable base de données, donc si l'exactitude est ce dont vous avez besoin, les réponses qu'elle donnera seront précises.

Pour expirer les anciens enregistrements, Elastic a une fonctionnalité intégrée TTL. Mongo vient de la présenter à partir de la version 2.2, je pense.

Étant donné que je ne connais pas vos autres exigences, telles que la taille attendue des données, les transactions, la précision ou l'apparence de vos filtres, il est difficile de formuler des recommandations spécifiques. J'espère qu'il y en a assez pour vous aider à démarrer.

352
gstathis