PostgreSQL "Search Everywhere": Volltext-, Trigramm- und partielle Indizes
Lerne, wie du eine schnelle âSearch everywhereâ in PostgreSQL fĂŒr interne Bildschirme entwirfst: wann Volltextsuche, TrigrammâIndizes oder partielle Indizes sinnvoll sind und wie du PrioritĂ€ten setzt.

Was âSearch everywhereâ fĂŒr interne Tools wirklich bedeutet
Auf einem internen Bildschirm heiĂt âSearch everywhereâ meist: âHilf mir, genau den Datensatz zu finden, an den ich gerade denke â schnell, auch wenn ich mich nicht exakt erinnere.â Nutzer browsen nicht; sie wollen direkt zu einem Kunden, Ticket, einer Rechnung oder einem GerĂ€t springen.
Deshalb fĂŒhlt sich eine langsame Suche schlimmer an als eine langsame Seite. Eine Seitenladung passiert einmal. Suche passiert oft mehrfach hintereinander, meist wĂ€hrend jemand in einem Anruf ist oder triagiert. Dauern Ergebnisse 2â3 Sekunden, Ă€ndert der Nutzer die Anfrage, löscht Zeichen, probiert ein anderes Stichwort und am Ende hast du mehr Last und mehr Frust.
Aus einem Suchfeld erwarten Nutzer mehrere Verhaltensweisen: Teiltreffer ("alex" findet "Alexander"), Toleranz fĂŒr kleine Tippfehler ("microsfot" findet trotzdem "Microsoft"), eine sinnvolle Reihenfolge der besten Treffer (exakte IDs oder EâMails oben), etwas Neuigkeitsbias und Filter, die standardmĂ€Ăig angewendet werden (offene Tickets, aktive Kunden).
Das Schwierige ist, dass ein Eingabefeld oft mehrere Intentionen verbirgt. Ein Agent könnte eine Ticketnummer einfĂŒgen, einen Namensfragment tippen, nach einer EâMail suchen oder eine Telefonnummer eingeben. Jede Absicht braucht oft eine andere Strategie, unterschiedliche Indizes und manchmal eine eigene RankingâRegel.
Also fang nicht mit Indizes an. Schreib zuerst die wenigen Suchintentionen auf, die deine Nutzer wirklich haben, und trenne IdentitĂ€tsfelder (IDs, EâMails) von fuzzy Feldern (Namen, Betreffe) und langen Texten (Notizen).
Starte damit, die Daten und das Suchverhalten zu benennen
Bevor du einen Index wĂ€hlst, notiere, was Leute tatsĂ€chlich eintippen. âPostgreSQL search everywhereâ klingt nach einer Funktion, ist aber meist eine Mischung sehr unterschiedlicher Suchen.
Interne Tools vermischen âharteâ Identifier (BestellâID, Ticketnummer, RechnungsâCode) mit âweichemâ Text (Kundenname, EâMail, Notizen, Tags). Diese Gruppen verhalten sich in PostgreSQL unterschiedlich; sie gleich zu behandeln ist eine schnelle AbkĂŒrzung zu langsamen Abfragen.
Als nÀchstes trenne die Verhaltensweisen:
- Exakte Suche: Jemand sucht
TCK-104883und erwartet ein prĂ€zises Ergebnis. - FuzzyâSuche: Jemand tippt
john smthund will eine verzeihende Ăbereinstimmung ĂŒber Namen (und vielleicht EâMails), die eine kurze Liste liefert. - Filtergetriebene Suche: Jemand wĂ€hlt âStatus = Openâ und âZugewiesen = Mirâ â hier ist das Textfeld sekundĂ€r.
Entscheide frĂŒh, ob Ergebnisse gerankt werden mĂŒssen (beste Treffer zuerst) oder einfach nur gefiltert. Ranking ist wichtig fĂŒr Notizen und lĂ€ngere Beschreibungen. FĂŒr IDs und EâMails wirkt Ranking oft zufĂ€llig und kostet zusĂ€tzlich.
Eine kurze Checkliste reicht meist aus:
- Welche Felder werden tÀglich durchsucht?
- Welche Eingaben sind exakt (IDs, Codes), fuzzy (Namen) oder langer Text (Notizen)?
- Welche Filter gelten praktisch bei jeder Suche?
- Brauchst du âbest matchâ Reihenfolge oder reicht jedes Match?
- Wie schnell wÀchst die Tabelle: Tausende, Hunderttausende oder Millionen?
Wenn du diese Entscheidungen vorher triffst, fĂŒhlen sich IndexâWahlen spĂ€ter nicht wie Raten an.
Die Basis: exakte Treffer und warum ILIKE oft schadet
Sichere die einfachen Gewinne zuerst. FĂŒr viele interne Bildschirme liefert ein normaler BâTreeâIndex sofort Ergebnisse fĂŒr exakte Treffer wie IDs, Bestellnummern, EâMails und externe Referenzen.
Wenn Leute einen exakten Wert einfĂŒgen, stelle sicher, dass deine Abfrage wirklich exakt ist. WHERE id = ... oder WHERE email = ... kann mit einem normalen Index extrem schnell sein. Ein UniqueâIndex auf EâMail zahlt sich oft doppelt aus: Geschwindigkeit und bessere DatenqualitĂ€t.
Probleme beginnen, wenn âsearch everywhereâ stillschweigend zu ILIKE wird. Eine Abfrage wie name ILIKE '%ann%' hat ein fĂŒhrendes Wildcard, sodass PostgreSQL keinen normalen BâTreeâIndex verwenden kann. Es prĂŒft viele Zeilen und wird mit wachsender Tabelle vorhersehbar langsamer.
PrĂ€fixsuche kann funktionieren, aber nur wenn das Muster am Anfang verankert ist: name ILIKE 'ann%'. Dabei spielen Details eine Rolle (Collation, CaseâHandling und ob du denselben Ausdruck indexiert hast, den du abfragst). Wenn deine UI caseâinsensitive sein muss, ist ein ĂŒblicher Ansatz lower(name) in der Abfrage und ein passender Index auf lower(name).
Hilfreich ist auĂerdem, zu vereinbaren, was âreaktionsschnellâ bedeutet:
- Etwa 200 ms oder weniger fĂŒr die Datenbankarbeit bei warmem Cache
- Unter 1 Sekunde EndeâzuâEnde inklusive Netzwerk und Rendering
- Kein sichtbarer Ladezustand fĂŒr hĂ€ufige Suchen
Mit solchen Zielen fĂ€llt die Entscheidung leichter, ob man bei exakten und PrĂ€fixâTreffern bleibt oder ob Volltextsuche oder TrigrammâIndizes nötig sind.
Wann Volltextsuche das richtige Werkzeug ist
Volltextsuche passt am besten, wenn Leute natĂŒrlichsprachlich tippen und erwarten, dass das System die richtigen EintrĂ€ge findet â nicht nur exakte Treffer. Denke an TicketâNachrichten, interne Notizen, lange Beschreibungen, KnowledgeâBaseâArtikel und Anrufprotokolle.
Der groĂe Vorteil ist Ranking. Statt eine lange Liste zu liefern, in der das beste Ergebnis vergraben ist, kann Volltextsuche nach Relevanz sortieren. In internen Tools zĂ€hlt das: Jemand braucht eine Antwort in Sekunden, nicht nach dem Durchsehen von 50 Zeilen.
Auf hoher Ebene hat Volltextsuche drei Teile:
- Ein
tsvector(der durchsuchbare Text, gespeichert oder generiert) - Ein
tsquery(was der Nutzer eingibt, umgewandelt in eine Abfrage) - Eine Sprachkonfiguration (wie Wörter normalisiert werden)
Die Sprachkonfiguration zeigt Verhalten. PostgreSQL entfernt hĂ€ufige Stoppwörter (wie âderâ oder âundâ) und wendet Stemming an, sodass z. B. âpayâ, âpaidâ und âpaymentâ ĂŒbereinstimmen können. Das ist groĂartig fĂŒr Notizen und Nachrichten, kann aber ĂŒberraschen, wenn jemand nach einem kurzen, hĂ€ufigen Wort sucht und nichts findet.
Synonyme sind ein weiterer Punkt. Sie helfen, wenn dein Unternehmen verschiedene Wörter fĂŒr dasselbe verwendet (z. B. ârefundâ vs. âchargebackâ), brauchen aber Pflege. Halte Synonymlisten kurz und basiere sie auf dem, was Support oder Ops wirklich eintippen.
Ein praktisches Beispiel: âcanât login after resetâ sollte Tickets finden, in denen steht âcannot log in after password resetâ, auch wenn die Wortwahl abweicht. Genau dieses ârelevante Findenâ ist die StĂ€rke der Volltextsuche und meist besser, als zu versuchen, ILIKE wie eine Suchmaschine wirken zu lassen.
Wann TrigrammâIndizes gewinnen
TrigrammâIndizes sind eine starke Wahl, wenn Nutzer Fragmente tippen, Tippfehler machen oder sich nur âirgendwie daran erinnernâ. Sie glĂ€nzen auf kurzen Textfeldern, wo Volltextsuche zu strikt ist: Personennamen, Firmennamen, TicketâBetreffe, SKUs, Bestellnummern und Produktcodes.
Ein Trigramm ist ein 3âZeichenâBlock. PostgreSQL vergleicht zwei Strings danach, wie viele Trigramme sie teilen. Deshalb kann es "Jon Smth" mit "John Smith" abgleichen oder "ACM" mit "ACME" finden, und es findet Treffer, wenn die Abfrage die Mitte eines Wortes ist.
Das ist oft der schnellste Weg zu einer verzeihenden âPostgreSQL search everywhereâ Box, wenn die Aufgabe âfinde die richtige Zeileâ ist und nicht âfinde Dokumente zu einem Thema".
Wo es die Volltextsuche schlÀgt
Volltextsuche ist gut fĂŒr lĂ€ngere Texte und semantisches Ranking, aber sie handhabt nicht natĂŒrlich Teilstrings und kleine Tippfehler auf kurzen Feldern. TrigrammâSuche ist fĂŒr diese Art von Fuzziness gemacht.
Schreibkosten gering halten
TrigrammâIndizes sind gröĂer und verursachen SchreibâOverhead, also sei selektiv. Indexiere nur die Spalten, die Nutzer wirklich verwenden:
- Name, EâMail, Firma, Benutzername
- Kurze Identifier (SKU, Code, Referenz)
- Ein knapper Titel (keine groĂen Notizâ oder Kommentarfelder)
Wenn du genau benennen kannst, welche Felder dein Team in die Suchbox tippt, hĂ€ltst du TrigrammâIndexierung meist klein und schnell.
Partielle Indizes fĂŒr die Filter, die Nutzer wirklich nutzen
Eine âSearch everywhereâ Box hat meist versteckte Defaults. Leute suchen innerhalb eines Workspaces, auf aktiven Objekten und ohne gelöschte EintrĂ€ge. Wenn diese Filter fast bei jeder Anfrage gelten, mache den hĂ€ufigen Fall schnell, indem du nur die Zeilen indizierst, die dazu passen.
Ein partieller Index ist ein normaler Index mit einer WHEREâKlausel. PostgreSQL hĂ€lt ihn kleiner, weil er nur EintrĂ€ge fĂŒr die fĂŒr dich wichtigen Zeilen speichert. Das bedeutet oft weniger Seiten zu lesen und bessere CacheâTrefferquoten.
Typische Ziele fĂŒr partielle Indizes sind aktive Zeilen (status = 'active'), SoftâDeletes (deleted_at IS NULL), TenantâScoping und âaktuelleâ Fenster (z. B. letzte 90 Tage).
Der SchlĂŒssel ist, dein UIâVerhalten abzubilden. Wenn der Screen gelöschte Zeilen immer ausblendet, sollten deine Abfragen deleted_at IS NULL immer enthalten und der partielle Index dieselbe Bedingung nutzen. Kleine Abweichungen, z. B. is_deleted = false an einer Stelle und deleted_at IS NULL an einer anderen, können verhindern, dass der Planner den Index nutzt.
Partielle Indizes funktionieren auch zusammen mit Volltext und Trigramm. Zum Beispiel behĂ€lt ein TextâIndex, der nur nichtâgelöschte Zeilen abdeckt, die IndexgröĂe unter Kontrolle.
Tradeâoff: Partielle Indizes helfen weniger bei seltenen Abfragen. Wenn jemand gelegentlich ĂŒber gelöschte DatensĂ€tze oder alle Workspaces sucht, kann PostgreSQL auf einen langsameren Plan zurĂŒckfallen. Löse das ĂŒber einen separaten AdminâPfad oder fĂŒge einen zweiten Index nur hinzu, wenn die seltene Abfrage hĂ€ufiger wird.
AnsÀtze mischen, ohne die Suche mysteriös zu machen
Die meisten Teams mischen Techniken, weil eine Suchbox mehrere Intentionen bedienen muss. Das Ziel ist, die Reihenfolge der Operationen klar zu machen, damit Ergebnisse vorhersehbar wirken.
Eine einfache PrioritĂ€tsreihenfolge hilft, egal ob du sie als separate Abfragen implementierst oder als eine Abfrage mit klarer CASEâLogik.
Eine vorhersehbare PrioritÀtsleiter
Beginne strikt und werde nur unschÀrfer, wenn nötig:
- Exakte Ăbereinstimmung zuerst (IDs, EâMail, Ticketnummer, SKU) mit BâTreeâIndizes
- PrÀfixsuche als nÀchstes, wo sinnvoll
- Trigramm danach fĂŒr Tippfehler und Fragmente in Namen und Titeln
- Volltextsuche zuletzt fĂŒr lĂ€ngere Notizen, Beschreibungen und Freitext
Wenn du dieselbe Leiter einhĂ€ltst, lernen Nutzer, was die Box âbedeutetâ. Sie hören auf zu denken, das System sei kaputt, wenn â12345â ein Ticket sofort findet, wĂ€hrend ârefund policyâ lĂ€nger in lĂ€ngeren Texten sucht.
Filter zuerst, dann Fuzziness
Unscharfe Suche wird teuer, wenn sie die ganze Tabelle betrachten muss. Verenge die Kandidatenmenge mit den Filtern, die Nutzer oft nutzen (Status, zugewiesenes Team, Datumsbereich, Konto), und fĂŒhre dann Trigramm oder Volltext auf dem Rest aus. Selbst ein schneller TrigrammâIndex fĂŒhlt sich langsam an, wenn er Millionen von Zeilen bewerten muss.
Es lohnt sich auch, eine einprĂ€gsame Regel in einem Satz fĂŒr nichtâtechnische Kollegen zu schreiben, z. B.: âWir matchen zuerst Ticketnummer exakt, dann Kundennamen mit TippfehlerâToleranz, dann Notizen.â Diese gemeinsame Definition verhindert spĂ€ter Diskussionen, warum ein Ergebnis auftauchte.
SchrittâfĂŒrâSchritt: eine Methode wĂ€hlen und sicher umsetzen
Eine schnelle âSearch everywhereâ Box ist eine Reihe kleiner Entscheidungen. Schreib sie zuerst auf, dann wird die Datenbankarbeit einfacher.
- Definiere die Eingaben. Ist es nur ein Feld, oder ein Feld plus Filter (Status, Besitzer, Datumsbereich)?
- WĂ€hle MatchâTypen pro Feld. IDs/Codes brauchen exakte Treffer. Namen/EâMails brauchen oft PrĂ€fix oder Fuzzy. Lange Notizen und Beschreibungen besser mit natĂŒrlicher Sprachsuche.
- FĂŒge die richtigen Indizes hinzu und verifiziere, dass sie genutzt werden. Lege den Index an und prĂŒfe deine reale Abfrage mit
EXPLAIN (ANALYZE, BUFFERS). - FĂŒge Ranking oder Sortierung hinzu, die zur Intention passt. Wenn Nutzer âinvoice 1042â tippen, sollten exakte Treffer oben stehen. Bei falsch geschriebenen Namen sollte ĂhnlichkeitsâRanking entscheiden.
- Teste mit echten Abfragen. Probiere Tippfehler, sehr kurze Begriffe (z. B. âalâ), lange eingefĂŒgte Texte, leere Eingabe und ânur Filterâ Modus.
Zum sicheren Ausliefern Ă€ndere jeweils nur eine Sache und halte Rollbacks einfach. Bei neuen Indizes auf groĂen Tabellen CREATE INDEX CONCURRENTLY bevorzugen, damit du Schreibzugriffe nicht blockierst. Wenn möglich, hinter FeatureâFlags ausrollen und Latenz vor/nach vergleichen.
Ein praktisches Muster fĂŒr âPostgreSQL search everywhereâ ist: erst exakte Treffer (schnell und prĂ€zise), dann Trigramm fĂŒr menschliche Felder mit Tippfehlern, und Volltext fĂŒr lange Texte, die von Ranking profitieren.
Ein realistisches Beispiel: eine Suchbox im SupportâAdminâPanel
Stell dir ein SupportâAdminâPanel vor, in dem das Team eine Suchbox hat, die Kunden, Tickets und sogar Notizen finden soll. Das ist das klassische âein Input, viele Bedeutungenâ Problem.
Der erste Gewinn ist, die Intention sichtbar zu machen, ohne Friktion einzufĂŒhren. Wenn die Anfrage wie eine EâMail oder Telefonnummer aussieht, behandle sie als KundenâLookup. Wenn sie wie eine TicketâID aussieht (z. B. "TKT-10482"), leite sie direkt zu Tickets. Alles andere fĂ€llt zurĂŒck auf Textsuche ĂŒber TicketâBetreff und Notizen.
FĂŒr Kundenlookup fĂŒhlen sich TrigrammâIndizes meist am besten an. Namen und Firmennamen sind unordentlich, und Leute tippen Fragmente. Ein TrigrammâIndex macht Suchen wie âjon smiâ oder âacmâ schnell und verzeihend.
FĂŒr TicketâNotizen nutze Volltextsuche. Notizen sind SĂ€tze, und man will meist relevante Treffer, nicht nur âenthĂ€lt dieses Substringâ. Ranking hilft, wenn Dutzende Tickets dasselbe Stichwort enthalten.
Filter sind wichtiger, als viele Teams erwarten. Wenn Agents in âoffenen Ticketsâ leben, fĂŒge einen partiellen Index hinzu, der nur offene Zeilen abdeckt. Dasselbe fĂŒr âaktive Kundenâ. So bleiben Indizes klein und der hĂ€ufige Pfad schnell.
Sehr kurze Queries verdienen Regeln, sonst macht die DB teure Arbeit fĂŒr Rauschen:
- 1â2 Zeichen: zeige kĂŒrzlich geöffnete Tickets und kĂŒrzlich aktualisierte Kunden
- 3+ Zeichen: fĂŒhre Trigramm fĂŒr Kundenfelder und Volltext fĂŒr TicketâText aus
- Keine klare Intention: zeige eine gemischte Liste, aber limitiere jede Gruppe (z. B. 10 Kunden und 10 Tickets)
HĂ€ufige Fehler, die Suche langsam oder verwirrend machen
Die meisten âwarum ist Suche langsam?â Bugs sind selbstverschuldet. Ziel ist nicht, alles zu indexieren, sondern das zu indexieren, was Nutzer wirklich tun.
Eine Falle ist, viele Indizes ânur fĂŒr den Fallâ hinzuzufĂŒgen. Lesezugriffe können besser werden, aber jeder Insert/Update hat jetzt Mehrarbeit. In internen Tools, wo DatensĂ€tze den ganzen Tag geĂ€ndert werden (Tickets, Bestellungen, Nutzer), zĂ€hlt Schreibgeschwindigkeit.
Ein anderer Fehler ist, Volltextsuche zu verwenden, wenn du eigentlich fehlertolerante LookupâSuche auf Namen oder EâMails brauchst. Volltext ist toll fĂŒr Dokumente und Beschreibungen. Es ist kein Allheilmittel fĂŒr âJonâ vs. âJohnâ oder âgmail.conâ vs. âgmail.comâ. DafĂŒr ist meist TrigrammâSuche besser.
Filter können stillschweigend deinen Plan zerstören. Wenn die meisten Suchen mit einem festen Filter passieren (z. B. status = 'open' oder org_id = 42), ist der beste Index oft ein partieller Index mit genau dieser Bedingung. Wenn du das vergisst, scannt PostgreSQL vielleicht viel mehr Zeilen als erwartet.
Einige Fehler treten immer wieder auf:
- Viele Indizes hinzufĂŒgen ohne Schreibkosten zu messen
- Volltext fĂŒr fehlertolerante AutocompleteâFĂ€lle erwarten
- Ignorieren, wie hÀufige Filter bestimmen, welcher Index benutzt werden kann
- Tests auf kleinen, sauberen Daten statt mit realer Terminfrequenz
- Nach einer Spalte sortieren, ohne passenden Index, was langsame Sorts erzwingt
Beispiel: Ein SupportâScreen sucht Tickets nach Betreff, Kundenname und Ticketnummer und sortiert dann nach letzter AktivitĂ€t. Wenn latest_activity_at nicht fĂŒr die gefilterte Menge indexiert ist (z. B. nur offene Tickets), kann dieser Sort die Geschwindigkeit zunichtemachen, die du durch den Suchindex gewonnen hast.
Kurze Checks vor dem Ausliefern
Bevor du eine âsearch everywhereâ Funktion fĂŒr fertig erklĂ€rst, werde konkret bei dem Verhalten, das du versprichst.
- Suchen Leute nach einem exakten Identifier (Ticketnummer, EâMail)?
- Erwarten sie fehlertolerante Ăbereinstimmungen bei Tippfehlern?
- Wollen sie gerankte Ergebnisse aus lÀngeren Notizen und Beschreibungen?
Wenn du Modi mischst, entscheide, welcher gewinnt, wenn sie kollidieren.
Identifiziere dann die 2â3 Felder, die die meisten Suchen treiben. Wenn 80% der Suchen per EâMail, Name und TicketâID passieren, optimiere zuerst diese Felder und behandle den Rest als sekundĂ€r.
Eine kurze PreâShipâCheckliste:
- BestĂ€tige den HauptâMatchâModus pro Feld (exakter Lookup, fuzzy Match oder gerankter Text)
- Liste die Filter, die Nutzer tÀglich anwenden, und stelle sicher, dass Indizes diese Kombinationen abdecken
- Entscheide, wie mit sehr kurzen und leeren Eingaben umgegangen wird (z. B. 2â3 Zeichen fĂŒr fuzzy verlangen; ârecentâ fĂŒr leere Eingaben zeigen)
- Mach die Sortierung erklÀrbar: zuletzt, bester Textmatch oder eine einfache kombinierte Regel
Teste schlieĂlich mit realistischer DatengröĂe und Timing, nicht nur auf Korrektheit. Eine Abfrage, die bei 1.000 Zeilen sofort wirkt, kann bei 1.000.000 stark nachlassen.
NĂ€chste Schritte: den Plan in ein schnelles internes Suchfeld verwandeln
Eine Suchbox bleibt schnell, wenn das Team sich auf ihr Verhalten einigt. Schreib die Regeln in klarer Sprache: was âmatchâ bedeutet (exakt, PrĂ€fix, fehlertolerant), welche Felder durchsucht werden und wie Filter das Ergebnis beeinflussen.
Behalte eine kleine Testmenge realer Suchanfragen und behandle sie wie eine RegressionsâSuite. Zehn bis zwanzig Abfragen genĂŒgen meist: ein paar gĂ€ngige Namen, einige partielle EâMails, ein Tippfehler, ein langer Notizauszug und ein âkein Ergebnisâ Fall. FĂŒhre sie vor und nach Ănderungen aus, damit PerformanceâArbeit Relevanz nicht heimlich bricht.
Wenn du interne Tools mit AppMaster (appmaster.io) baust, hilft es, diese Suchregeln zusammen mit dem Datenmodell und der BusinessâLogik zu definieren, damit UIâVerhalten und DatenbankâEntscheidungen nicht auseinanderlaufen, wenn Anforderungen sich Ă€ndern.
FAQ
Behandle es als âfinde schnell den genauen Datensatz, den ich meineâ, nicht als Browsen. Schreib zuerst die wenigen echten Suchintentionen der Nutzer auf (ID-Lookup, Name/EâMail-Lookup mit Tippfehlern, Suche in langen Notizen) und welche Standardfilter fast immer angewendet werden. Diese Entscheidungen sagen dir, welche Abfragen du ausfĂŒhren solltest und welche Indizes sich lohnen.
ILIKE '%term%' hat ein fĂŒhrendes Wildcard, deshalb kann PostgreSQL in der Regel keinen normalen BâTreeâIndex verwenden und muss viele Zeilen prĂŒfen. Das fĂŒhlt sich bei kleinen Tabellen vielleicht in Ordnung an, verlangsamt aber stark, wenn die Daten wachsen. Wenn du Substringâ oder fehlertolerante Ăbereinstimmungen brauchst, plane fĂŒr Trigrammâ oder VolltextâSuche statt darauf zu hoffen, dass ILIKE skaliert.
Verwende exakte Vergleiche wie WHERE id = $1 oder WHERE email = $1 und unterstĂŒtze sie mit einem BâTree (bei EâMails oder Codes oft unique). Exakte Lookups sind die gĂŒnstigsten Suchanfragen und machen Ergebnisse auĂerdem vorhersehbar. Wenn Nutzer eine vollstĂ€ndige Ticketnummer oder EâMail einfĂŒgen, leite die Anfrage zuerst ĂŒber diesen Pfad.
Bevorzuge ein PrĂ€fixmuster wie name ILIKE 'ann%' und indexiere dieselbe Ausdrucksform konsistent. FĂŒr zuverlĂ€ssiges caseâinsensitive Verhalten fragen viele Teams lower(name) ab und legen einen Index auf denselben Ausdruck an, damit der Planner ihn nutzen kann. Wenn das Muster nicht am Anfang verankert ist, reicht PrĂ€fixsuche nicht aus.
Nutze TrigrammâIndizes, wenn Nutzer Fragmente tippen, kleine Tippfehler machen oder sich nur an âetwas Ăhnlichesâ erinnern â besonders auf kurzen Feldern wie Namen, Betreff, SKU oder Benutzernamen. Trigramme vergleichen 3âZeichenâChunks und sind gut geeignet, um Mittelteile eines Strings zu finden oder nahe Ăbereinstimmungen bei Rechtschreibfehlern zu erkennen. Sei selektiv: TrigrammâIndizes sind gröĂer und erhöhen die Schreibkosten.
Verwende Volltextsuche, wenn Leute ganze SĂ€tze oder SchlĂŒsselwörter in lĂ€ngeren Inhalten wie Notizen, Nachrichten, Beschreibungen oder KnowledgeâBaseâTexten suchen. Der groĂe Vorteil ist RelevanzâRanking: die besten Treffer steigen an die Spitze, statt dass Nutzer lange Listen durchsuchen mĂŒssen. Achte auf sprachspezifisches Verhalten wie Stemming und StopâWords â gut fĂŒr Prosa, aber bei sehr kurzen, hĂ€ufigen Wörtern ĂŒberraschend.
FĂŒge partielle Indizes hinzu, wenn die meisten Suchanfragen dieselben Filter enthalten, z. B. deleted_at IS NULL, status = 'open' oder eine Mandanten/WorkspaceâEinschrĂ€nkung. Da der Index nur die relevanten Zeilen enthĂ€lt, bleibt er kleiner und in realen Workloads oft schneller. Achte darauf, dass deine Abfrage exakt dieselbe Bedingung nutzt wie der partielle Index, sonst ignoriert PostgreSQL ihn.
Nutze eine konsistente PrioritĂ€tsleiter, damit Ergebnisse stabil wirken: exakte Ăbereinstimmung zuerst (IDs/EâMails), dann PrĂ€fix wo passend, danach Trigramm fĂŒr verzeihliche Name/TitleâTreffer und zuletzt Volltext fĂŒr lange Notizen/Beschreibungen. Wende Standardfilter frĂŒh an, um die Kandidatenmenge zu reduzieren, bevor du teure unscharfe Suchen startest. So bleiben Performance und Relevanz auch bei wachsendem Datenvolumen stabil.
Setze einfache Regeln wie: erfordere 3+ Zeichen bevor unscharfe Suche lĂ€uft, und zeige bei sehr kurzen Eingaben stattdessen kĂŒrzlich bearbeitete oder offene DatensĂ€tze. Sehr kurze Eingaben erzeugen viel LĂ€rm und können teure Arbeit fĂŒr geringen Nutzen auslösen. Entscheide auĂerdem, wie leere Eingaben behandelt werden, damit die UI die Datenbank nicht mit âmatch allesâ Abfragen bombardiert.
Lege den Index an und ĂŒberprĂŒfe dann die echte Abfrage mit EXPLAIN (ANALYZE, BUFFERS) auf realistischen Datenmengen, nicht nur im DevâDatensatz. Rolle Ănderungen schrittweise aus und halte Rollbacks einfach; bei groĂen Tabellen CREATE INDEX CONCURRENTLY nutzen, um Schreibsperren zu vermeiden. Wenn du die OberflĂ€che in AppMaster (appmaster.io) baust, definiere die Suchregeln zusammen mit dem Datenmodell und der BusinessâLogik, damit UIâVerhalten und DBâEntscheidungen nicht auseinanderlaufen.


