64 votes

Pourquoi Solr est-il tellement plus rapide que Postgres?

J'ai récemment passé de Postgres pour Solr et a vu un ~50x vitesse jusqu'à nos requêtes. Les requêtes de nous exécuter impliquer plusieurs plages, et de nos données est véhicule listes. Par exemple: "Trouver tous les véhicules avec un kilométrage < 50 000 et de 5 000 $ < prix < 10 000$, à faire=Mazda..."

J'ai créé des indices sur toutes les colonnes dans Postgres, il devrait donc être assez juste de la comparaison. En regardant le plan de requête dans Postgres bien qu'il n'était encore qu'à l'aide d'un indice unique, puis de numérisation (je suppose, car il ne pouvait pas faire usage de tous les différents indices).

Comme je le comprends, Postgres et Solr utilisation vaguement similaire structures de données (B-arbres), et ils ont à la fois des données en cache dans la mémoire. Alors je me demandais où de telles une grande différence de performances.

Quelles différences dans l'architecture pourrait expliquer cela?

132voto

jpountz Points 6914

Tout d'abord, Solr n'est pas l'utilisation de B-arbres. Lucene (la bibliothèque sous-jacente utilisée par Solr), l'indice de rendu de lecture seule segments. Pour chaque segment, Lucene maintient un terme du dictionnaire, qui se compose de la liste des termes qui apparaissent dans le segment, lexicographiquement triés. À la recherche d'un terme dans ce terme dictionnaire est faite à l'aide d'une recherche binaire, de sorte que le coût d'un seul terme de recherche est - O(log(t)) où t est le nombre de termes. Au contraire, en utilisant l'indice d'une norme SGBDR frais O(log(d)) d où d est le nombre de documents. Lorsque de nombreux documents partagent la même valeur dans un champ, cela peut être une grande victoire.

En outre, Lucene committer Uwe Schindler ajout du support pour les très performant plage de nombres de requêtes il y a quelques années. Pour chaque valeur d'un champ numérique, Lucene magasins de plusieurs valeurs avec des précisions différentes. Cela permet de Lucene pour exécuter gamme requêtes de manière très efficace. Depuis votre cas d'utilisation semble un levier numérique de la gamme des requêtes beaucoup, cela peut expliquer pourquoi Solr est donc beaucoup plus rapide. (Pour plus d'informations, lire la javadoc qui sont très intéressants et donnent des liens vers des documents de recherche.)

Mais Solr ne peut le faire que parce qu'il n'a pas toutes les contraintes qu'un SGBDR. Par exemple, Solr est très mauvais à la mise à jour d'un document unique à un moment (il préfère les mises à jour par lot).

39voto

kgrittn Points 6058

Vous n'avez pas vraiment en dire beaucoup sur ce que vous avez à régler votre instance PostgreSQL ou de vos requêtes. Il n'est pas rare de voir un 50x vitesse sur un PostgreSQL requête par le biais de réglage et/ou de réitérer votre requête dans un format qui optimise le mieux.

Juste cette semaine, il y avait un rapport au travail qui quelqu'un avait écrit à l'aide de Java et de plusieurs requêtes dans un chemin qui, en se basant sur la manière dont il avait obtenu dans les quatre heures, allait prendre environ un mois. (Il fallait frapper cinq tables différentes, chacune avec des centaines de millions de lignes.) Je l'ai réécrit en utilisant plusieurs expressions de table communes et une fonction de fenêtre, de sorte qu'il a couru en moins de dix minutes et a généré les résultats escomptés tout droit sorti de la requête. C'est un 4400x vitesse.

Peut-être la meilleure réponse à votre question n'a rien à voir avec les détails techniques de la façon dont les recherches peuvent être effectuées dans chaque produit, mais plus à voir avec la facilité d'utilisation pour votre cas d'utilisation particulier. Clairement, vous avez pu trouver le moyen rapide de recherche avec Solr avec moins de problèmes que PostgreSQL, et il ne peut pas venir vers le bas pour quelque chose de plus.

Je suis notamment un court exemple de la façon dont les recherches de texte pour plusieurs critères pourrait être fait dans PostgreSQL, et comment quelques petits changements peuvent faire une grande différence en termes de performances. Pour le garder simple et rapide, je suis juste la course de la Guerre et de la Paix dans la forme d'un texte dans une base de données de test, à chaque "document" d'une seule ligne de texte. Des techniques similaires peuvent être utilisés pour arbitraire de champs à l'aide de l' hstore type ou JSON colonnes, si les données doivent être vaguement définis. Où il y a plusieurs colonnes, avec leurs propres indices, les avantages de l'utilisation d'index ont tendance à être beaucoup plus grand.

-- Create the table.
-- In reality, I would probably make tsv NOT NULL,
-- but I'm keeping the example simple...
CREATE TABLE war_and_peace
  (
    lineno serial PRIMARY KEY,
    linetext text NOT NULL,
    tsv tsvector
  );

-- Load from downloaded data into database.
COPY war_and_peace (linetext)
  FROM '/home/kgrittn/Downloads/war-and-peace.txt';

-- "Digest" data to lexemes.
UPDATE war_and_peace
  SET tsv = to_tsvector('english', linetext);

-- Index the lexemes using GiST.
-- To use GIN just replace "gist" below with "gin".
CREATE INDEX war_and_peace_tsv
  ON war_and_peace
  USING gist (tsv);

-- Make sure the database has statistics.
VACUUM ANALYZE war_and_peace;

Une fois mis en place, pour l'indexation, je montre quelques recherches avec les nombres de lignes et des horaires avec les deux types d'indices:

-- Find lines with "gentlemen".
EXPLAIN ANALYZE
SELECT * FROM war_and_peace
  WHERE tsv @@ to_tsquery('english', 'gentlemen');

84 lignes, gist: 2.006 ms, gin: 0.194 ms

-- Find lines with "ladies".
EXPLAIN ANALYZE
SELECT * FROM war_and_peace
  WHERE tsv @@ to_tsquery('english', 'ladies');

184 lignes, gist: 3.549 ms, gin: 0.328 ms

-- Find lines with "ladies" and "gentlemen".
EXPLAIN ANALYZE
SELECT * FROM war_and_peace
  WHERE tsv @@ to_tsquery('english', 'ladies & gentlemen');

1 ligne, gist: 0.971 ms, gin: 0.104 ms

Maintenant, depuis le GIN indice était environ 10 fois plus rapide que l'Essentiel index vous pourriez vous demander pourquoi quelqu'un voudrait utiliser GiST pour l'indexation des données de texte. La réponse est que le GiST est généralement plus rapide à entretenir. Donc, si vos données de texte est très volatile, l'Essentiel de l'indice pourrait gagner sur l'ensemble de la charge, tandis que le GIN indice permettrait de gagner si vous êtes seulement intéressé dans le temps de recherche, ou pour une lecture principalement de la charge de travail.

Sans l'indice ci-dessus requêtes prendre n'importe où à partir de 17.943 ms à 23.397 ms car ils doivent numériser l'ensemble de la table et de vérifier pour un match sur chaque ligne.

Le GIN indexé de recherche pour les lignes avec les deux "dames" et "messieurs" est de plus de 172 fois plus rapide que l'analyse d'une table, exactement de la même base de données. De toute évidence les avantages de l'indexation est de plus en plus dramatique avec plus de documents que ceux qui ont été utilisés pour ce test.

L'installation est, bien sûr, une chose une seule fois. Avec un seuil de déclenchement de maintenir l' tsv colonne, toutes les modifications apportées seraient instantanément être consultée sans refaire toute l'installation.

Avec la lenteur de la requête PostgreSQL, si vous montrez de la structure de la table (y compris index), le problème de la requête, et le résultat de l'exécution de EXPLAIN ANALYZE de votre question, quelqu'un peut presque toujours de repérer le problème et de suggérer comment le faire courir plus vite.

7voto

Mark O'Connor Points 33201

Solr est conçu principalement pour la recherche de données, pas pour le stockage. Il permet de rejeter une grande partie des fonctionnalités nécessaires à partir d'un SGBDR. Donc, il (ou plutôt lucene) se concentre sur le plan purement de l'indexation des données.

Comme vous l'avez sans doute remarqué, Solr permet de rechercher et de récupérer des données à partir de son index. C'est de cette dernière (en option) capacité, qui conduit à la question naturelle... "puis-je utiliser Solr comme une base de données?"

La réponse est oui, et je vous renvoie à la suivante:

Mon opinion personnelle est que Solr est considéré comme une base de cache entre mon application et les données maîtrisé dans ma base de données. De cette façon je peux obtenir le meilleur des deux mondes.

6voto

Yavar Points 5314

Cette plus grande différence est qu'un Lucene/Solr indice est comme une seule table de base de données sans aucune prise en charge pour les requêtes relationnelles (Joint). Rappelez-vous qu'un indice est généralement là que pour prendre en charge la recherche et de ne pas être la principale source de données. Si votre base de données peut être un "troisième forme normale", mais l'indice va être complètement dé-normalisé et contient la plupart du temps simplement les données nécessaires à la recherche.

Une autre raison possible est généralement bases de données souffrent de la fragmentation interne, ils ont besoin pour effectuer trop de semi-aléatoire des tâches d'e/S sur les énormes demandes.

Ce que cela signifie, par exemple, compte tenu de l'indice de l'architecture de bases de données, la requête conduit à l'index qui à son tour conduire à des données. Si les données à récupérer est largement répandu, le résultat va prendre un certain temps et qui semble être ce qui se passe dans les bases de données.

1voto

Tejas Patil Points 3872

Merci de lire ceci et de cela.

Solr (Lucene) crée un index inversé qui est l'endroit où la récupération de données est assez rapide. J'ai lu que PostgreSQL dispose également d'une installation similaire mais vous ne savez pas si vous aviez utilisé.

Les différences de rendement observées peuvent également être mis sur le compte de "ce qui est recherché ?", "quelles sont les requêtes de l'utilisateur ?"

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X