it-swarm.com.de

Warum ist Solr so viel schneller als Postgres?

Ich bin kürzlich von Postgres zu Solr gewechselt und habe bei unseren Abfragen eine 50-fache Geschwindigkeit festgestellt. Die von uns durchgeführten Abfragen umfassen mehrere Bereiche, und unsere Daten sind Fahrzeuglisten. Zum Beispiel: "Finde alle Fahrzeuge mit Laufleistungen <50.000, $ 5.000 <Preis <10.000, Marke = Mazda ..."

Ich habe Indizes für alle relevanten Spalten in Postgres erstellt, daher sollte es ein ziemlich fairer Vergleich sein. Wenn man sich den Abfrageplan in Postgres ansieht, obwohl er nur einen einzigen Index verwendet und dann scannt (ich gehe davon aus, dass nicht alle verschiedenen Indizes verwendet werden konnten).

So wie ich es verstehe, verwenden Postgres und Solr vage ähnliche Datenstrukturen (B-Bäume) und beide speichern Daten im Speicher. Ich frage mich also, woher ein so großer Leistungsunterschied kommt.

Welche Unterschiede in der Architektur würden dies erklären?

63
cberner

Erstens verwendet Solr keine B-Bäume. Ein Lucene-Index (die von Solr verwendete zugrunde liegende Bibliothek) besteht aus einem schreibgeschützten Segmente . Lucene verwaltet für jedes Segment ein Wörterbuch mit Begriffen, das aus der Liste der im Segment enthaltenen Begriffe besteht und lexikografisch sortiert ist. Das Nachschlagen eines Begriffs in diesem Begriffswörterbuch erfolgt über eine binäre Suche. Die Kosten für eine Suche nach einem einzigen Begriff betragen also O(log(t)), wobei t die Anzahl der Begriffe ist. Im Gegensatz dazu kostet die Verwendung des Index eines Standard-RDBMS O(log(d)), wobei d die Anzahl der Dokumente ist. Wenn viele Dokumente für ein Feld denselben Wert haben, kann dies ein großer Gewinn sein.

Darüber hinaus hat Lucene-Committer Uwe Schindler vor einigen Jahren die Unterstützung für sehr performante numerische Bereichsabfragen hinzugefügt. Für jeden Wert eines numerisches Feld speichert Lucene mehrere Werte mit unterschiedlichen Genauigkeiten. Dadurch kann Lucene Bereichsabfragen sehr effizient ausführen. Da Ihr Anwendungsfall häufig numerische Bereichsabfragen nutzt, kann dies erklären, warum Solr so viel schneller ist. (Für weitere Informationen lesen Sie die Javadocs, die sehr interessant sind, und geben Sie Links zu relevanten Forschungsberichten.)

Solr kann dies jedoch nur, weil es nicht alle Einschränkungen eines RDBMS aufweist. Solr ist beispielsweise sehr schlecht darin, ein einzelnes Dokument zu aktualisieren (es bevorzugt Stapelaktualisierungen).

130
jpountz

Sie haben nicht wirklich viel darüber gesagt, was Sie getan haben, um Ihre PostgreSQL-Instanz oder Ihre Abfragen zu optimieren. Es ist nicht ungewöhnlich, dass eine PostgreSQL-Abfrage um das 50-fache beschleunigt wird, wenn Ihre Abfrage in einem Format optimiert und/oder neu erstellt wird, das die Optimierung verbessert.

Erst in dieser Woche gab es einen Bericht bei der Arbeit, den jemand mit Java) und mehreren Abfragen geschrieben hatte, die, je nachdem, wie weit es in vier Stunden gekommen war, ungefähr einen Monat in Anspruch nahmen würden (Es mussten fünf verschiedene Tabellen mit jeweils Hunderten von Millionen Zeilen gefunden werden.) Ich habe es mit mehreren CTEs und einer Fensterfunktion neu geschrieben, sodass es in weniger als zehn Minuten ausgeführt und die gewünschten Ergebnisse direkt aus der Abfrage generiert wurde Das ist eine 4400-fache Geschwindigkeit.

Vielleicht hat die beste Antwort auf Ihre Frage nichts mit den technischen Details zu tun, wie Suchen in jedem Produkt durchgeführt werden können , sondern eher mit der Leichtigkeit für Ihren speziellen Anwendungsfall. Es ist klar, dass Sie den schnellen Weg gefunden haben, mit Solr mit weniger Mühe als mit PostgreSQL zu suchen, und es kann sein, dass nicht mehr als das herauskommt.

Ich füge ein kurzes Beispiel hinzu, wie Textsuchen nach mehreren Kriterien in PostgreSQL durchgeführt werden können und wie ein paar kleine Änderungen einen großen Leistungsunterschied bewirken können. Um es schnell und einfach zu halten, führe ich einfach Krieg und Frieden in Textform in eine Testdatenbank ein, wobei jedes "Dokument" eine einzelne Textzeile ist. Ähnliche Techniken können für beliebige Felder unter Verwendung der Spalten hstore type oder JSON verwendet werden, wenn die Daten lose definiert werden müssen. Wenn es separate Spalten mit eigenen Indizes gibt, sind die Vorteile der Verwendung von Indizes in der Regel viel größer.

-- 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;

Einmal für die Indizierung eingerichtet, zeige ich einige Suchvorgänge mit Zeilenzahlen und Timings für beide Indextypen:

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

84 Zeilen, 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 Zeilen, 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 Reihe, Gist: 0,971 ms, Gin: 0,104 ms

Da der GIN-Index etwa zehnmal schneller war als der Gist-Index, fragen Sie sich vielleicht, warum jeder Gist für die Indizierung von Textdaten verwenden würde. Die Antwort ist, dass Gist im Allgemeinen schneller zu warten ist. Wenn Ihre Textdaten also sehr volatil sind, gewinnt der Gist-Index möglicherweise bei der Gesamtauslastung, während der GIN-Index gewinnt, wenn Sie nur an der Suchzeit oder an einer meistens lesenden Auslastung interessiert sind.

Ohne den Index dauern die obigen Abfragen zwischen 17,943 ms und 23,397 ms, da sie die gesamte Tabelle durchsuchen und jede Zeile auf Übereinstimmung prüfen müssen.

Die GIN-indizierte Suche nach Zeilen mit "Damen" und "Herren" ist über 172-mal schneller als ein Tabellenscan in genau derselben Datenbank. Offensichtlich wären die Vorteile der Indizierung bei größeren Dokumenten dramatischer als bei diesem Test.

Das Setup ist natürlich eine einmalige Sache. Mit einem Auslöser zum Verwalten der Spalte tsv können alle vorgenommenen Änderungen sofort durchsucht werden, ohne dass das Setup erneut ausgeführt werden muss.

Wenn Sie bei einer langsamen PostgreSQL-Abfrage die Tabellenstruktur (einschließlich der Indizes), die Problemabfrage und die Ausgabe von EXPLAIN ANALYZE Ihrer Anfrage kann fast immer jemand das Problem erkennen und vorschlagen, wie es schneller ausgeführt werden kann.


UPDATE (9. Dezember 16)

Ich habe nicht erwähnt, was ich verwendet habe, um die vorherigen Timings zu erhalten, aber basierend auf dem Datum, an dem es wahrscheinlich die Hauptversion 9.2 gewesen wäre. Ich bin gerade auf diesen alten Thread gestoßen und habe ihn mit Version 9.6.1 auf derselben Hardware erneut versucht, um festzustellen, ob die dazwischen liegende Leistungsoptimierung in diesem Beispiel hilfreich ist. Die Abfragen für nur ein Argument erhöhten die Leistung nur um etwa 2%, aber die Suche nach Zeilen mit beiden "Damen" und "Herren" verdoppelte sich ungefähr in der Geschwindigkeit auf 0,053 ms (dh 53 Mikrosekunden) bei Verwendung des GIN-Index (invertiert).

37
kgrittn

Solr ist in erster Linie für die Suche nach Daten und nicht für die Speicherung konzipiert. Auf diese Weise kann ein Großteil der für ein RDMS erforderlichen Funktionen verworfen werden. Es (oder besser lucene ) konzentriert sich also auf die reine Indizierung von Daten.

Wie Sie zweifellos festgestellt haben, ermöglicht Solr das Suchen und Abrufen von Daten aus dem Index. Es ist die letztere (optionale) Funktion, die zu der natürlichen Frage führt ... "Kann ich Solr als Datenbank verwenden?"

Die Antwort ist ein qualifiziertes Ja, und ich verweise Sie auf Folgendes:

Meiner persönlichen Meinung nach ist Solr am besten als durchsuchbarer Cache zwischen meiner Anwendung und den in meiner Datenbank gespeicherten Daten zu verstehen. Auf diese Weise bekomme ich das Beste aus beiden Welten.

6
Mark O'Connor

Der größte Unterschied besteht darin, dass ein Lucene/Solr-Index wie eine Einzeltabellendatenbank ohne Unterstützung für relationale Abfragen (JOINs) ist. Denken Sie daran, dass ein Index normalerweise nur zur Unterstützung der Suche und nicht als primäre Datenquelle dient. Ihre Datenbank befindet sich möglicherweise in der "dritten Normalform", der Index wird jedoch vollständig entnormalisiert und enthält meist nur die Daten, die durchsucht werden müssen.

Ein weiterer möglicher Grund ist, dass Datenbanken im Allgemeinen intern fragmentiert sind und bei großen Anforderungen zu viele halbzufällige E/A-Aufgaben ausführen müssen.

Betrachtet man beispielsweise die Indexarchitektur einer Datenbank, führt die Abfrage zu den Indizes, die wiederum zu den Daten führen. Wenn die wiederherzustellenden Daten weit verbreitet sind, wird das Ergebnis lange dauern, und dies scheint in Datenbanken der Fall zu sein.

6
Yavar

Bitte lesen Sie this und this .

Solr (Lucene) erstellt einen invertierten Index , mit dem das Abrufen von Daten erheblich beschleunigt wird. I read dass PostgreSQL auch eine ähnliche Funktion hat, aber nicht sicher, ob Sie diese verwendet haben.

Die beobachteten Leistungsunterschiede lassen sich auch auf "Was wird gesucht?", "Was sind die Benutzeranfragen?"

1
Tejas Patil