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 Sie eine PostgreSQL-Abfrage um 50x beschleunigen, indem Sie Ihre Abfrage in einem Format optimieren und/oder neu formatieren, das für eine bessere Optimierung sorgt.
Gerade diese Woche gab es einen Bericht bei der Arbeit, den jemand mit Java und mehreren Abfragen auf eine Weise geschrieben hatte, die, je nachdem, wie weit sie in vier Stunden gekommen war, ungefähr einen Monat in Anspruch nehmen würde. (Es musste fünf verschiedene Tabellen mit jeweils Hunderten von Millionen Zeilen durchlaufen.) Ich schrieb es mit mehreren CTEs und einer Fensterfunktion um, so dass es in weniger als zehn Minuten lief und die gewünschten Ergebnisse direkt aus der Abfrage erzeugte. Das ist eine 4400-fache Beschleunigung.
Vielleicht ist die beste Antwort auf Ihre Frage hat nichts mit den technischen Einzelheiten zu tun, wie sucht in jedem Produkt durchgeführt werden kann, sondern mehr mit einfacher Bedienung für Ihren speziellen Anwendungsfall zu tun. Es war klar, dass Sie den schnellen Weg, mit Solr zu suchen, mit weniger Schwierigkeiten finden konnten als PostgreSQL, und es kann zu nichts anderem kommen.
Ich bin ein kurzes Beispiel, wie Text sucht nach mehreren Kriterien in PostgreSQL getan werden kann, und wie ein paar kleine Optimierungen einen großen Leistungsunterschied machen können. Um es schnell und einfach zu halten, führe ich einfach Krieg und Frieden in Textform in eine Testdatenbank, wobei jedes "Dokument" eine einzelne Textzeile ist. Ähnliche Techniken können für beliebige Felder mit den Spalten hstore
oder JSON
verwendet werden, wenn die Daten lose definiert sein müssen. Wenn separate Spalten mit eigenen Indizes vorhanden sind, sind die Vorteile bei der Verwendung von Indizes wesentlich 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 einrichten, zeigen, dass ich ein paar Recherchen mit Zeilenanzahl und Timings mit beiden Arten von Indizes:
-- Find lines with "gentlemen".
EXPLAIN ANALYZE
SELECT * FROM war_and_peace
WHERE tsv @@ to_tsquery('english', 'gentlemen');
84 Zeilen, Kern: 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 Zeile, Kern: 0,971 ms, Gin: 0,104 ms
Da nun der GIN-Index etwa 10-mal schneller als der GiST Index war fragen Sie sich vielleicht, warum jemand GiST für die Indizierung verwenden würde, Textdaten. Die Antwort lautet, dass GiST im Allgemeinen schneller zu warten ist. Wenn Ihre Textdaten also sehr unbeständig sind, könnte der GiST-Index bei einer allgemeinen Auslastung gewinnen, während der GIN-Index gewinnen würde, wenn Sie nur an der Suchzeit oder an einer Lesearbeitslast interessiert sind.
Ohne den Index nehmen die obigen Abfragen zwischen 17,943 ms und 23,397 ms, da sie die gesamte Tabelle scannen und nach einer Übereinstimmung in jeder Zeile suchen müssen.
Die GIN-indizierte Suche nach Zeilen mit "Damen" und "Gentlemen" ist über 172 mal schneller als ein Tabellenscan in genau derselben Datenbank. Offensichtlich wären die Vorteile der Indexierung bei größeren Dokumenten dramatischer als bei diesem Test.
Das Setup ist natürlich eine einmalige Sache. Mit einem Auslöser, um die Spalte tsv
beizubehalten, wären alle vorgenommenen Änderungen sofort durchsuchbar, ohne das Setup zu wiederholen.
Mit einer langsamen PostgreSQL-Abfrage, wenn Sie die Tabellenstruktur (einschließlich Indizes), die Problemabfrage und die Ausgabe von EXPLAIN ANALYZE
Ihrer Abfrage zeigen, kann jemand fast immer das Problem erkennen und vorschlagen, wie es ausgeführt wird schneller.
UPDATE (9. Dezember '16)
Ich habe nicht erwähnt, was ich verwenden, um die vorherigen Zeitpunkt zu bekommen, aber auf der Grundlage des Zeitpunkt wäre es wahrscheinlich die Version 9.2 wichtigsten gewesen sein. Ich bin gerade über diesen alten Thread gestolpert und habe es auf der gleichen Hardware mit Version 9.6.1 erneut versucht, um zu sehen, ob irgendeine der dazwischenliegenden Performance-Einstellungen dieses Beispiel unterstützt. Die Abfragen für nur ein Argument haben nur um etwa 2% in der Leistung zugenommen, aber die Suche nach Linien mit beiden "Damen" und "Gentlemen" über die doppelte Geschwindigkeit auf 0,053 ms (dh 53 Mikrosekunden) bei Verwendung der GIN (invertiert) Index.
Haben Sie Postgres Volltextsuche oder einfache 'LIKE' Anfragen verwendet? –
Das relationale Modell war nie dazu gedacht, bei hässlichen Fragen wie "Gib mir all die Leute, die an einem Mittwoch geboren wurden und zwischen 2003 und 2005 ein rotes Auto besaßen", gut zu funktionieren. Dafür gibt es Suchmaschinen (wie Lucene). Indizes helfen manchmal, Speichereinstellungen helfen immer. – wildplasser
Ich bin ein wenig verwirrt durch Ihre Frage, also frage ich hier: http://dba.stackexchange.com/questions/34014/using-solr-lucene-for-searching-non-text-tables Will/can Solr/Lucene Suchvorgänge sind schneller als PostgreSQL, auch wenn keine Volltextsuche durchgeführt wird? – alfonx