6 Punkte von GN⁺ 2023-07-13 | 1 Kommentare | Auf WhatsApp teilen
  • Die Volltextsuche von PostgreSQL ist ein Ansatz, bei dem sich Suchfunktionen ohne separate Suchmaschine durch die Kombination von tsvector, tsquery, @@, ts_rank und GIN-Indizes aufbauen lassen
  • Suchbegriffe und Dokumente werden auf Lexem-Ebene normalisiert, und mit Operatoren wie AND, OR, NOT und FOLLOWED BY lässt sich ein großer Teil üblicher Suchsyntax umsetzen
  • GIN-Indizes reduzierten die Suchzeit in der Beispielumgebung von über 200 ms auf etwa 4 ms, aber bei vielen Treffern können die Kosten für Ranking und Sortierung mit ts_rank zum Flaschenhals werden
  • Relevanz-Tuning wird umgesetzt, indem Signale wie Titelgewichtung, Zahl der Stimmen, Bewertung, Genre und Aktualität in die Sortierformel aufgenommen oder Spalten per setweight gewichtet werden
  • Fehlertoleranz, Facettensuche, Autovervollständigung, exakte Phrasensuche und hybride Suche sind ebenfalls möglich, aber in PostgreSQL müssen die Bausteine direkt zusammengesetzt werden, und bei großen Datensätzen sollten Leistungsgrenzen geprüft werden

Der Ansatz der PostgreSQL-Volltextsuche

  • PostgreSQL stellt für die Volltextsuche niedrigstufige Bausteine bereit, die sich zu Suchmaschinenfunktionen kombinieren lassen
  • Dieser Ansatz ist flexibel, erfordert aber mehr Implementierungsaufwand als Elasticsearch, Typesense oder Meilisearch, deren Hauptzweck Volltextsuche ist
  • Die Beispielabfragen verwenden den Datensatz Wikipedia Movie Plots von Kaggle
    • Er enthält 34.000 Filmtitel
    • Die Größe im CSV-Format beträgt etwa 81 MB

Zentrale Bausteine

  • Die PostgreSQL-Volltextsuche arbeitet im Kern mit den folgenden Elementen
    • tsvector: speichert durchsuchbaren Text als Liste normalisierter Lexeme
    • tsquery: stellt eine normalisierte Suchanfrage dar
    • @@: Match-Operator zur Prüfung, ob eine tsquery zu einem tsvector passt
    • ts_rank, ts_rank_cd: berechnen den Relevanz-Score von Suchergebnissen
    • GIN-Indizes: invertierte Indizes, um tsvector effizient abzufragen

tsvector und Suchkonfigurationen

  • tsvector speichert eine sortierte Liste von Lexemen
    • Ein Lexem ist ähnlich wie ein Token, aber als normalisierte Zeichenkette so aufbereitet, dass verschiedene Formen desselben Wortes auf eine Form abgebildet werden
    • In der englischen Konfiguration werden Großbuchstaben in Kleinbuchstaben umgewandelt und Endungen zur Normalisierung entfernt
  • Wenn man einen englischen Satz mit to_tsvector parst, werden Stoppwörter wie „I“, „to“ und „an“ entfernt
    • „refuse“ und „Refusing“ werden beide zu refus
    • Satzzeichen werden ignoriert
    • Wortpositionen und Gewichtungen im Originaltext werden ebenfalls gespeichert
  • Verwendet man statt der Suchkonfiguration english die Konfiguration simple, werden Wörter in der Form übernommen, in der sie im Text vorkommen
    • „refuse“ und „refusing“ bleiben unterschiedliche Lexeme
    • Die Konfiguration simple ist besonders nützlich für Spalten mit Labels oder Tags
  • PostgreSQL bietet eingebaute Suchkonfigurationen für mehrere Sprachen, aber keine für CJK (Chinesisch, Japanisch, Koreanisch)
    • Für nicht unterstützte Sprachen kann die Konfiguration simple in der Praxis gut funktionieren
    • Ob das für CJK ausreichend ist, ist allerdings nicht sicher

tsquery und Darstellung von Suchanfragen

  • tsquery ist ein Datentyp zur Darstellung normalisierter Suchanfragen
    • Suchbegriffe müssen bereits normalisierte Lexeme sein
    • Mehrere Suchbegriffe lassen sich mit den Operatoren AND, OR, NOT und FOLLOWED BY kombinieren
  • to_tsquery, plainto_tsquery und websearch_to_tsquery helfen dabei, vom Benutzer eingegebenen Text in eine passende tsquery zu überführen
    • Ihre zentrale Aufgabe ist es, die im Eingabetext enthaltenen Wörter zu normalisieren
  • Mit websearch_to_tsquery lassen sich Anfragen erzeugen, die einer gewöhnlichen Suchleiste näherkommen
    • darth vader wird als logisches AND behandelt, bei dem beide Wörter im Dokument vorkommen müssen
    • OR-Suche und das Ausschließen von Wörtern sind ebenfalls möglich
    • Phrasensuche wird als Folge von Wörtern in der richtigen Reihenfolge ausgedrückt
  • In der englischen Konfiguration werden Stoppwörter wie „the“ entfernt, sodass bei manchen Phrasensuchen fast die gesamte Formulierung verschwinden kann
    • In solchen Fällen liefert die Konfiguration simple möglicherweise die erwarteten Ergebnisse
  • Der Operator @@ wird verwendet, um zu prüfen, ob eine tsquery zu einem tsvector passt

GIN-Indizes und Suchleistung

  • GIN steht für Generalized Inverted Index und ist ein Indextyp, der für Abfragen entwickelt wurde, die nach Elementwerten innerhalb zusammengesetzter Werte suchen
  • GIN kann nicht nur für Textsuche, sondern auch für JSON-Abfragen verwendet werden
  • Es lässt sich eine tsvector-Spalte anlegen, die mehrere durchsuchbare Spalten zusammenführt, und darauf ein GIN-Index erstellen
  • In der Beispielumgebung reduzierte ein GIN-Index die Suchzeit von über 200 ms auf etwa 4 ms

Ranking und Relevanzberechnung

  • Für eine gute Sucherfahrung sollten Ergebnisse nach Relevanz sortiert werden
  • PostgreSQL bietet dafür zwei vordefinierte Ranking-Funktionen: ts_rank und ts_rank_cd
    • Beide Funktionen berücksichtigen die Häufigkeit des Auftretens von Suchbegriffen
    • ts_rank_cd bezieht zusätzlich die Nähe zwischen passenden Lexemen ein
  • Relevanz hängt stark von der jeweiligen Anwendung ab
    • Die Standard-Ranking-Funktionen sind eher ein Ausgangspunkt; bei Bedarf kann man eigene Ranking-Funktionen erstellen oder sie mit anderen Faktoren kombinieren
  • ts_rank muss auf die search-Spalte jedes Ergebnisses zugreifen
    • Wenn die WHERE-Bedingung viele Zeilen trifft, muss PostgreSQL alle diese Zeilen für Ranking-Berechnung und Sortierung besuchen
    • In der Beispielumgebung wurde eine Anfrage in 5 bis 7 ms zurückgegeben, aber eine Anfrage wie darth OR vader, bei der mehr als 1.000 Ergebnisse gerankt werden mussten, brauchte etwa 80 ms

Relevanz-Tuning

  • Relevanz auf Basis der Worthäufigkeit ist ein guter Standard, aber in den Daten können wichtigere Signale als reine Häufigkeit stecken
  • Im Filmdatensatz lassen sich zum Beispiel folgende Signale in die Relevanz einbeziehen
    • Treffer im Titel höher gewichten als Treffer in Beschreibung oder Handlung
    • Beliebtere Filme anhand von Bewertung oder Zahl der Stimmen nach oben setzen
    • Wenn ein Nutzer Komödien bevorzugt, Komödien höher platzieren
    • Neuere Titel als relevanter behandeln als ältere
  • Dedizierte Suchmaschinen bieten Funktionen, mit denen festgelegt werden kann, wie verschiedene Spalten oder Felder das Ranking beeinflussen

Boosting nach Zahlen, Datum und exakten Werten

  • PostgreSQL bietet kein direktes Boosting auf Basis anderer Spalten, aber Ranking ist letztlich eine Sortierformel, daher können eigene Signale ergänzt werden
  • Um die Zahl der Stimmen zu berücksichtigen, kann man dem Ranking-Score einen auf der Stimmenzahl basierenden Boost hinzufügen
    • Im Beispiel wird ein Logarithmus verwendet, um den Einfluss abzuflachen
    • Ein Koeffizient von 0.01 bringt den Booster auf eine ähnliche Skala wie den Ranking-Score
  • Es lassen sich auch komplexere Funktionen bauen, die eine Bewertung nur dann boosten, wenn die Zahl der Stimmen einen bestimmten Schwellenwert überschreitet
  • Wenn ein bestimmtes Genre angehoben werden soll, kann eine Funktion wie valueBooster verwendet werden, die nur dann einen Koeffizienten zurückgibt, wenn ein Wert mit einem bestimmten Spaltenwert übereinstimmt

Spaltengewichtungen

  • Lexemen in einem tsvector können Gewichte zugewiesen werden
  • PostgreSQL unterstützt vier Gewichtsstufen: A, B, C und D
    • A ist die höchste Gewichtung
    • D ist die niedrigste und der Standardwert
  • Mit der Funktion setweight lässt sich die Gewichtung beim Erzeugen einer tsvector-Spalte steuern
  • Gibt man der Titelspalte ein höheres Gewicht, erscheinen Filme, deren Suchbegriff im Titel vorkommt, weiter oben in den Ergebnissen und erhalten einen höheren Ranking-Score
  • Die Beschränkung auf nur vier Gewichtsklassen ist einschränkend, und die Gewichte müssen bei der Berechnung von tsvector angewendet werden

Fehlertoleranz und Fuzzy Search

  • PostgreSQL unterstützt bei Verwendung von tsvector und tsquery weder Fuzzy Search noch Fehlertoleranz direkt
  • Unter der Annahme, dass Tippfehler auf der Anfrageseite liegen, lässt sich dies folgendermaßen umsetzen
    • Alle Lexeme aus dem Inhalt in einer separaten Tabelle indexieren
    • Für jedes Wort der Anfrage Kandidatenwörter anhand von Ähnlichkeit oder Levenshtein-Distanz suchen
    • Die Anfrage so anpassen, dass die gefundenen Wörter eingeschlossen werden
    • Die Suche mit der angepassten Anfrage ausführen
  • Im Beispiel wird Levenshtein distance verwendet, weil Suchmaschinen dieses Verfahren für Fuzzy Search einsetzen
  • Nachdem eine Liste möglicher Kandidatenwörter vorliegt, muss die Anfrage so angepasst werden, dass alle diese Wörter berücksichtigt werden

Facettensuche

  • Facettensuche wird vor allem auf E-Commerce-Websites häufig genutzt, damit Nutzer den Suchraum schrittweise eingrenzen können
  • In PostgreSQL lässt sie sich umsetzen, indem Kategorien manuell definiert und dann zur WHERE-Bedingung der Suche hinzugefügt werden
  • Es ist auch möglich, Kategorien algorithmisch auf Basis vorhandener Daten zu erzeugen
    • Im Beispiel wird auf Basis des Filmjahres eine „Decade“-Facette erstellt
    • Die Anzahl der Treffer pro Jahrzehnt kann mitberechnet und in Klammern angezeigt werden
  • Um mehrere Facetten in einer einzigen Anfrage abzurufen, können CTEs kombiniert werden
  • Dieser Ansatz kann bei kleinen bis mittelgroßen Datensätzen gut funktionieren, bei sehr großen Datensätzen aber langsam werden

Umfang und Grenzen einer PostgreSQL-Suchmaschine

  • Durch die Kombination der PostgreSQL-Bausteine für Volltextsuche lässt sich eine ziemlich fortgeschrittene Suchmaschine bauen
  • Eine auf PostgreSQL basierende Suche unterstützt außerdem Joins und ACID-Transaktionen
    • Das sind Funktionen, die andere Suchmaschinen normalerweise nicht bieten
  • Weitere fortgeschrittene Suchthemen, die sich behandeln lassen, sind unter anderem
    • Vorschläge und Autovervollständigung
    • Exaktes Phrasen-Matching
    • Hybride Suche in Kombination mit pg-vector
  • Diese Funktionen sind mit PostgreSQL möglich, aber die Bausteine müssen direkt zusammengesetzt werden
  • In manchen Fällen kann die Leistung bei sehr großen Datensätzen nachlassen
  • Der Folgebeitrag part 2 vergleicht die Implementierung von Suche in PostgreSQL mit dem Hinzufügen von Elasticsearch zur Infrastruktur und der Synchronisierung der Daten

1 Kommentare

 
GN⁺ 2023-07-13
Hacker-News-Meinungen
  • Man sollte nicht versuchen, das auf eine Weise zu machen, die Elasticsearch-Funktionen nachahmt
    In den 2000ern habe ich einmal mit MySQL 3.x eine Suchmaschine gebaut, die EXIF-Daten aus Bildern parste und eine dreistufige Taxonomie samt Zählwerten indexierte. Das war etwas, woran mehrere teure Anbieter scheiterten; Autonomy schaffte nicht einmal die oberste Kategorie
    Nach 6 Wochen hatte ich es gerade so geschafft, mit fragilem SQL, bei dem schon eine andere Reihenfolge der SELECT-Spalten die Performance änderte. Noch einmal möchte ich das nicht machen. Datenbanken sind im Kern zwar weitgehend ähnlich geblieben, aber Suchmaschinen haben sich deutlich weiterentwickelt
    Aus intellektueller Neugier kann man das machen, aber Suche ist nicht einfach Tokenisierung und fertig. Bald kommen Anforderungen wie Facettennavigation, Mehrsprachigkeit, automatische Synonyme, Rechtschreibvorschläge à la „Did you mean“ und Performance in großem Maßstab hinzu, und man manövriert sich selbst in eine Sackgasse. Der eigenen geistigen Gesundheit zuliebe ist es besser, eine Suchmaschine zu nutzen; für die Synchronisierung von PG und ES gibt es auch Tools wie ZomboDB oder PGSync

    • In diesem Thread sind zwei unterschiedliche Diskussionen vermischt. Wenn man eine kundenseitige Suchmaschine baut, ist es richtig, ein leistungsfähiges Tool wie Elasticsearch zu verwenden und das Rad nicht neu zu erfinden
      Wenn dagegen Datenanalysten oder Entwickler Textspalten in einer großen Datenbank flexibler durchsuchen möchten als mit LIKE/ILIKE, kann es einfacher und schneller sein, innerhalb derselben Datenbank einen Full-Text-Search-Index/eine Full-Text-Search-Tabelle anzulegen und damit 90 % des Weges zu schaffen
  • Ich bin gespannt auf Teil 2 mit dem Vergleich Postgres vs. Elasticsearch. Eine Anwendung in unserem Unternehmen nutzt PG für Objekt-CRUD und Elastic für die Suche; wir haben den Aufwand, zwei Datenspeicher synchron zu halten, völlig unterschätzt und prüfen tatsächlich, Elasticsearch zu entfernen

    • Der Ansatz, den ich früher verwendet habe, war, Elasticsearch als Ziel zu behandeln, das jederzeit neu aufgebaut werden kann
      Alle 5 Minuten sucht ein Cronjob in der DB nach zu indexierenden Objekten mit last_modified_at > last_indexing_started_timestamp, indexiert sie in Elasticsearch und setzt danach last_indexing_started_timestamp auf den Startzeitpunkt der Synchronisierung. Objekte, die zwischen Start und Ende des Laufs geändert wurden, werden dann beim nächsten Lauf erfasst
      Wenn Elasticsearch neu aufgebaut werden muss, leert man den letzten Indexierungszeitpunkt und synchronisiert von Anfang an neu; dadurch wird das System selbstheilend und die Synchronisierung gerät nicht aus dem Takt
    • In einem früheren Job hatten wir eine ähnliche Konfiguration, und sie war nicht besonders schwierig. Jedes Mal, wenn eine Entität in PG aktualisiert wurde, wurde eine Nachricht gesendet und asynchron nach ES repliziert; die ES-Seite holte sich die Daten per ID aus PG und füllte sie ein
      Wie bei asynchronen Jobs immer braucht man Monitoring und Retries, aber ES war stabil und schnell, daher gab es selten Probleme. Allerdings waren die Konsistenzanforderungen locker: Es reichte, wenn der aktuelle Zustand aus PG innerhalb einer vernünftigen Zeit in ES ankam. Bei anderen Anforderungen kann das anders aussehen
    • Wir sind ähnlich vorgegangen: Postgres für CRUD, Elastic für Suche, und haben nicht nur die Synchronisierung der beiden Speicher unterschätzt, sondern mit begrenztem Personal und begrenzter Erfahrung auch den Betrieb eines stabilen Elastic-Clusters
      Nachdem wir auf Postgres-Full-Text-Search mit Index- und Query-Gewichtungen umgestellt hatten, konnten wir alles Nötige innerhalb von Postgres erledigen – nur mit Update-Triggern und sehr schnellen Suchabfragen
    • Mich würde interessieren, ob ihr zombodb ausprobiert habt [https://www.zombodb.com/]
    • Ich habe das schon gemacht; selbst mit reichlich Erfahrung war es eine schwierige Aufgabe, und manche Ergebnisse waren sogar schlechter. Die meisten waren ähnlich, nur ein sehr kleiner Teil war besser
      Insgesamt war es ein Erfolg, und der Betriebsaufwand sank stark genug, dass sich die investierte Engineering-Zeit locker amortisierte, aber es ist nichts, womit man leichtfertig anfangen sollte
      Je nach Bedarf können materialisierte Views, normale Views oder Trigger besser sein. Die eingebaute Textsuche passt möglicherweise nicht zum Anwendungsfall, und eine Alternative zu bauen muss nicht zwangsläufig schwierig sein
  • Ohne p50/p99-Abfragezeiten unter realistischer Last ist das schwer als belegt anzusehen. Eine Suchmaschine, die Ergebnisse in 1 Minute zurückgibt, ist nicht „fortgeschritten“, und mit einer relationalen Datenbank wie Postgres ist das auf dem Papier natürlich auch möglich

    • Als Autor plane ich einen Folgeartikel mit einem Vergleich zu Elasticsearch, aber Benchmarks werde ich vermutlich nicht versuchen. Welches realistische Szenario man auch konstruiert, es wird nie genau zu den jeweiligen Anwendungsfällen passen
      Im Großen und Ganzen stimme ich zu; in großem Maßstab, etwa ab ein paar Millionen Datensätzen, würde ich diesen Ansatz wahrscheinlich nicht verwenden. Mein Hauptinteresse war, wie viel Funktionalität man nachbauen kann
      Bei kleinen Suchanwendungsfällen hat man Vorteile wie weniger zu wartende Infrastruktur, starke Konsistenz und Joins. Bei Xata denken wir auch über einen sanften Übergang nach: erst Postgres in kleinem Maßstab nutzen und dann mit möglichst wenigen Breaking Changes zu Elasticsearch wechseln
    • Als ich mit jemandem interviewte, der früher bei Google war, hörte ich, dass sie alle Suchergebnisse für bereits gesehene Suchbegriffe cachen und beim Aktualisieren des Index auch die gecachten Ergebnisse mit aktualisieren
      Aus dieser Perspektive sind schnelle Suchergebnisse an sich nicht besonders überraschend. Man kann die gecachten Ergebnisse im Hintergrund fortlaufend aktualisieren und sie bei einer Anfrage einfach ausliefern. Dieses Caching und die Antwortzeit scheinen unabhängig davon zu sein, wie schnell die eigentliche Berechnung der Suchergebnisse ist
    • Es ist problematisch, p50/p99 unter realistischer Last zu verlangen. Wie kann man die wirklich reale Last einer Suchmaschine erzeugen, wenn viele Menschen gar nicht tatsächlich suchen? Mit zufälligen Suchbegriffen darauf einzuschlagen ist nicht realistisch
      Manche Nutzer haben langsame Verbindungen, und bestimmte Suchbegriffe wie Erdbeben können nur in bestimmten Regionen stark ansteigen
      Sind die Suchbegriffe zu zufällig, gibt es keine Ergebnisse im Cache und es sieht schlechter aus als in Wirklichkeit; sind sie nicht zufällig genug, sieht es besser aus als in Wirklichkeit
    • Lucene, also die Grundlage von Elasticsearch und Solr, verwendet einen invertierten Index, und das im Artikel erwähnte GIN nutzt denselben Ansatz
      Daher liegen die Vorteile von ES und ähnlichen Systemen in der horizontalen Skalierung über mehrere Nodes hinweg oder in zusätzlichen Funktionen, die auf dem Hauptindex aufsetzen
    • Ich nutze Postgres-Full-Text-Search, und sie funktioniert gut. Allerdings muss man wissen, wie man Zeilen in einer Query ranken will
      Nur ts_rank zu verwenden ist perfekt, aber normalerweise möchte man das Ranking mit anderen Relevanzmetriken korrigieren. Wenn man löst, dass diese Metrik nicht als primäres Ranking-Kriterium dienen kann, sind die Ergebnisse so schnell wie eine Abfrage auf einer normalen DB-Tabelle mit Index
  • Als Teenager habe ich einmal von Grund auf eine Suchmaschine und eine Datenbank gebaut, obwohl ich von beidem nicht viel verstand. Ich wollte sehen, wie weit man kommt und wie schnell man einigermaßen relevante Suchergebnisse zurückgeben kann.
    Eine einfache Datenbank und eine einfache Suchmaschine schnell zu bauen, ist auch für Amateurprogrammierer ziemlich leicht. Wenn man grundlegende Informatik-Algorithmen versteht und weiß, wie man Betriebssystem und Hardware nutzt, kann man das in ein bis zwei Monaten schaffen.
    Selbst in einer High-Level-Sprache war die Geschwindigkeit nicht schlecht; auf einem Laptop von 2003 waren es etwa 250.000 QPS. Mit Sharding ist auch die Skalierbarkeit kein großes Problem. Indexierung, Sperren und Konsistenz sind komplexer als Speichern und Abfragen.
    Das wirklich große Problem ist die Subjektivität der Suche. Wenn es darum geht, was man wirklich finden möchte, wie man etwas findet, wenn man selbst nicht weiß, wonach man sucht, wie man Leute aufhält, die das System missbrauchen wollen, und wie man komplexe Queries und Datensätze handhabt, steigt der Schwierigkeitsgrad um mehrere Größenordnungen.

    • 250.000 RPS wirken ziemlich hoch, denn selbst SQLite schafft das heute nicht in der Größenordnung. Ein invertierter Index dürfte noch teurer sein, und RocksDB kommt auf etwa 130.000 RPS; selbst diese Zahl stammt vermutlich von Hardware, die stärker ist als mein Laptop, oder meine Umgebung ist falsch konfiguriert.
      Mich würde interessieren, ob du wirklich eine Allzweck-Datenbank verwendet hast und ob diese Zahl stimmt. Ich wüsste gern, welche Techniken du eingesetzt hast, um diese Engines zu übertreffen.
    • Das größte Problem beim Bau einer Suchmaschine ist nicht QPS, sondern die Größe des zu indexierenden Datensatzes. Wenn die Suchstruktur in den Arbeitsspeicher einer einzelnen Maschine passt, ist die Latenz praktisch nahe 0 und man kann faktisch unbegrenzte QPS liefern.
      Wird sie größer, braucht man kreative Lösungen, und ab dann tauchen verschiedene Trade-offs auf.
    • Ich frage mich, ob das irgendwo als Open Source veröffentlicht ist.
  • Eines der Probleme bei der Suche innerhalb von Postgres ist, dass Suche eine CPU-intensive Aufgabe ist und sich zunehmend auch in Richtung GPU-Nutzung bewegt. Idealerweise möchte man die CPU der Datenbank für transaktionale Updates des Kern-Datenmodells freihalten.
    Ich habe oft gesehen, dass ES- und Solr-Cluster während des Reindexierens auf mehr als 10 Nodes mit 100 % laufen oder selbst im Normalbetrieb auf mehr als 10 Nodes 30–50 % CPU nutzen. Die entsprechende Datenbank kann zum Beispiel auf einer AWS-L/XL-Instanz mit 50–100 GB Daten und etwa 30 % CPU-Auslastung laufen.
    Wenn man die gesamte Such-CPU in die Hauptdatenbank verlagert, muss man die DB anschließend sharden. Für Side Projects sind PG-Erweiterungen für Suche, rekursive Joins, Vektoren usw. aber trotzdem angenehm, spannend und einfach.

    • Könnte man das nicht lösen, indem man die Suche auf einer Read-only-Replik ausführt?
  • Ich habe das früher tatsächlich gemacht und es ziemlich schnell hinbekommen.
    https://austingwalters.com/fast-full-text-search-in-postgres...
    Die Website ist aktuell https://askhn.ai.

  • Kombiniert man solche Techniken mit pgvector, kann man über Embeddings auch relevante Inhalte finden. Das fühlte sich ziemlich magisch an.

    • Kannst du das etwas genauer erklären oder Material nennen, in das man sich einlesen kann?
    • Ich finde es interessant, dass Leute solche hacky Wege gehen, obwohl man etwas wie Vespa verwenden könnte. In Bezug auf Performance, Relevanz, Skalierbarkeit und Developer Experience halte ich Vespa für um Größenordnungen besser.
  • Nebenbei: Es heißt nicht „Dark“ Vader, sondern Darth Vader. Als Kind dachte ich auch, es sei „Dark“.

    • In manchen Übersetzungen, etwa im Französischen, heißt er tatsächlich Dark Vador, wodurch dieser „Fehler“ verbreitet wurde.
    • Diese Stelle im Artikel hat mich so gestört, dass ich mich auf den Rest nicht mehr konzentrieren konnte. Wie kann man das Yoda-Zitat kennen und trotzdem noch Dark Vader schreiben?
  • Ein sehr guter und klarer Artikel. Auch SQLite bietet als Standard-Plugin fortgeschrittene Indexfunktionen und Stemming.
    Für Englisch funktioniert SQLite ebenfalls gut.

    • Ich habe die Unterlagen zu meinen Experimenten mit SQLite gefunden.
      https://github.com/daitangio/knowledge
      Es lohnt sich, das auszuprobieren. Es ist ziemlich leistungsfähig.
    • Ich frage mich, ob man das auch mit FDW machen könnte. Wenn man nur die zu durchsuchenden Daten repliziert, gäbe es nicht viele schreibende Worker, daher könnte das bei mittelgroßen Daten gut funktionieren.
  • Guter Artikel, aber die Aussage, PostgreSQL unterstütze keine Fuzzy Search, ist teilweise falsch. Die Erweiterung pg_trgm und ein GIN-Trigramm-Index unterstützen Fuzzy-Search-Anwendungsfälle wie die Beispiele in diesem Artikel.
    https://www.postgresonline.com/article_pfriendly/169.html
    Queries können dadurch deutlich schneller werden, allerdings um den Preis eines höheren Speicherverbrauchs und längerer Arbeitszeit bei Updates.