Pourquoi Solr est-il plus rapide que Postgres?

je suis récemment passé de Postgres à Solr et j'ai vu un ~50x accélérer nos requêtes. Les requêtes que nous exécutons impliquent plusieurs plages, et nos données sont des listes de véhicules. Par exemple: "trouver tous les véhicules avec le kilométrage < 50 000, 5 000 $ < Prix < 10 000$, faire=Mazda..."

j'ai créé des indices sur toutes les colonnes pertinentes dans Postgres, il devrait être une comparaison assez juste. En regardant le plan de requête dans Postgres bien qu'il était encore en utilisant un seul index et puis scanning (je suppose parce qu'il ne pouvait pas faire usage de tous les différents indices).

D'après ce que j'ai compris, Postgres et Solr utilisent des structures de données vaguement similaires (arbres B), et ils mettent tous les deux des données en mémoire. Je me demande donc d'où vient une telle différence de performance.

quelles différences d'architecture expliquerait cela?

62
demandé sur jpountz 2012-04-07 12:40:25

5 réponses

tout d'abord, Solr n'utilise pas de B-trees. Un index de Lucène (la bibliothèque sous-jacente utilisée par Solr) est fait d'un segments en lecture seule . 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. Rechercher un terme dans ce dictionnaire terme est fait en utilisant une recherche binaire, de sorte que le coût d'une recherche à terme unique est O(log(t)) où t est le nombre de termes. Au contraire, à l'aide de l'indice d'un coûts standard du SGBDR O(log(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 a ajouté le soutien pour très performant les requêtes de portée numérique Il ya quelques années. Pour chaque valeur d'un champ numérique , Lucene stocke plusieurs valeurs avec des précisions différentes. Cela permet à Lucene d'exécuter des requêtes de portée très efficacement. Puisque votre cas d'utilisation semble tirer parti des requêtes de portée numérique beaucoup, cela pourrait expliquer pourquoi Solr est tellement 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 que possède un RDBMS. Par exemple, Solr est très mauvais pour mettre à jour un seul document à la fois (il préfère les mises à jour par lots).

124
répondu jpountz 2012-04-07 11:31:43

vous n'avez pas vraiment dit grand chose sur ce que vous avez fait pour accorder votre instance PostgreSQL ou vos requêtes. Il n'est pas inhabituel de voir une vitesse de 50x sur une requête PostgreSQL en ajustant et/ou en reformatant votre requête dans un format qui optimise mieux.

juste cette semaine, il y avait un rapport au travail que quelqu'un avait écrit en utilisant Java et plusieurs requêtes d'une manière qui, basée sur la distance qu'il avait obtenu en quatre heures, allait prendre environ un mois à remplir. (Il nécessaire pour atteindre les cinq tables différentes, chacune avec des centaines de millions de lignes.) Je l'ai réécrit en utilisant plusieurs CTEs 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 désirés directement hors de la requête. C'est un 4400x accéléré.

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ée dans chaque produit, mais plus à faire avec facilité d'utilisation pour votre cas particulier. Il est clair que vous avez pu trouver le moyen rapide de chercher avec Solr avec moins de problèmes que PostgreSQL, et il ne peut pas descendre à rien de plus que cela.

j'inclus un bref exemple de la façon dont les recherches textuelles pour plusieurs critères peuvent être effectuées dans PostgreSQL, et comment quelques petits ajustements peuvent faire une grande différence de performance. Pour que ce soit simple et rapide, Je ne fais que lancer guerre et Paix sous forme de texte dans une base de données d'essai, chaque "document" étant une seule ligne de texte. Des techniques similaires peuvent être utilisées pour des champs arbitraires en utilisant les colonnes hstore ou JSON , si les données doivent être définies de manière lâche. Lorsqu'il y a des colonnes séparées avec leurs propres indices, les avantages d'utiliser les indices ont tendance à être beaucoup plus grands.

-- 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 établi pour l'indexation, je montre quelques recherches avec le nombre de lignes et les minuteries avec les deux types d'index:

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

84 rows, 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 rows, 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 rangée, gist: 0.971 ms, gin: 0.104 ms

maintenant, puisque l'index GIN était environ 10 fois plus rapide que l'index GiST, vous pourriez vous demander pourquoi n'importe qui utiliserait GiST pour indexer des données de texte. La réponse est que GiST est généralement plus rapide à maintenir. Donc, si vos données texte est très volatile l'index GiST pourrait gagnez sur la charge globale, tandis que l'index GIN gagnerait si vous êtes seulement intéressé par le temps de recherche ou pour une charge de travail en lecture-la plupart du temps.

sans l'index les requêtes ci-dessus prennent n'importe où de 17.943 ms à 23.397 ms puisqu'ils doivent balayer la table entière et vérifier une correspondance sur chaque ligne.

la recherche indexée GIN pour les lignes avec" ladies "et" gentlemen " est plus de 172 fois plus rapide qu'un scan de table dans exactement la même base de données. De toute évidence les avantages de l'indexation serait plus spectaculaire avec des documents plus volumineux que ceux utilisés pour ce test.

le montage est, bien sûr, une chose unique. Avec un déclencheur pour maintenir la colonne tsv , toutes les modifications effectuées seraient instantanément consultables sans réécriture de la configuration.

avec une requête PostgreSQL lente, si vous montrez la structure de la table (y compris les index), la requête de problème, et la sortie de l'exécution EXPLAIN ANALYZE de votre requête, quelqu'un peut presque toujours repérer le problème et suggérer comment le faire fonctionner plus rapidement.


mise à jour (Dec 9 '16)

Je n'ai pas mentionné ce que j'ai utilisé pour obtenir les horaires précédents, mais basé sur la date, il aurait probablement été la 9.2 libération majeure. Je me suis juste produit à travers ce vieux fil et je l'ai essayé de nouveau sur le même matériel en utilisant la version 9.6.1, pour voir si l'un des réglages de performance entre-temps AIDE cet exemple. Les requêtes pour un seul argument ont augmenté seulement dans la performance d'environ 2%, mais la recherche de lignes avec à la fois "ladies" et "messieurs" à peu près doublé en vitesse à 0,053 ms (i.e., 53 microsecondes) en utilisant l'index GIN (inversé).

35
répondu kgrittn 2016-12-09 20:35:59

cette plus grande différence est qu'un index Lucene/Solr est comme une base de données à une seule table sans aucun support pour les requêtes relationnelles (jointures). Rappelez-vous qu'un index est habituellement seulement là pour soutenir la recherche et ne pas être la source principale des données. Ainsi, votre base de données peut se trouver dans la "troisième forme normale", mais l'index sera complètement dénormalisé et contiendra principalement les données nécessaires pour être recherché.

une autre raison possible est que les bases de données fragmentation interne, ils doivent effectuer trop de tâches d'e/s semi-aléatoires sur des demandes énormes.

cela signifie, par exemple, que si l'on considère l'architecture d'index d'une base de données, la requête mène aux index qui, à leur tour, mènent aux données. Si les données à récupérer sont largement répandues, le résultat sera long et cela semble être ce qui se passe dans les bases de données.

6
répondu Yavar 2012-04-07 10:19:33

Solr est conçu principalement pour la recherche de données, pas pour le stockage. Cela lui permet de rejeter une grande partie des fonctionnalités requises d'un SGDR. Ainsi, il (ou plutôt lucene ) se concentre sur des données purement d'indexation.

comme vous l'avez sans doute découvert, Solr permet à la fois de rechercher et d'extraire des données de son index. C'est cette dernière capacité (optionnelle) qui mène à la question naturelle... "Puis-je utiliser Solr comme base de données?"

la réponse est un oui qualifié, et je vous renvoie à ce qui suit:

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

6
répondu Mark O'Connor 2017-05-23 11:47:19

s'il vous Plaît lire ce et ce .

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

les différences de rendement que vous avez observées peuvent aussi être attribuées à "ce qui est recherché ?", "quelles sont les utilisateur les requêtes ?"

1
répondu Tejas Patil 2017-05-23 12:18:14