RUM-Index erstellen und abfragen

Mit RUM-Indexen in AlloyDB for PostgreSQL können Sie Volltextsuchanfragen beschleunigen, indem Sie Positions- und Attributinformationen zusammen mit Lexemen im Index speichern. Sie können die Erweiterung rum aktivieren, um RUM-Indexe zu erstellen und das Relevanzranking, die Suche nach Wortgruppen und die zeitstempelbasierte Sortierung zu optimieren.

Hinweis

Zum Erstellen der RUM-Erweiterung benötigen Sie die Datenbankrolle alloydbsuperuser.

Die IAM-Rolle (Identity and Access Management) „AlloyDB Admin“ (roles/alloydb.admin) gewährt die volle Kontrolle über AlloyDB-Ressourcen, aber nicht die Datenbankrolle alloydbsuperuser. Zum Erstellen der Erweiterung muss Ihnen ein Administrator explizit die Datenbankrolle alloydbsuperuser zuweisen.

Weitere Informationen zum Zuweisen von Rollen finden Sie unter IAM-Nutzer oder -Dienstkonto zu einem Cluster hinzufügen.

RUM-Erweiterung erstellen

Sie müssen die RUM-Erweiterung einmal pro Datenbank erstellen.

  1. Stellen Sie über psql oder einen anderen Client eine Verbindung zu Ihrer AlloyDB-Datenbank her. Weitere Informationen finden Sie unter Verbindung zu einer Clusterinstanz herstellen.
  2. Führen Sie den folgenden SQL-Befehl aus, um die Erweiterung zu erstellen:

    CREATE EXTENSION IF NOT EXISTS rum;
    

RUM-Index erstellen

Wenn Sie Volltextsuchanfragen optimieren möchten, erstellen Sie einen RUM-Index für Ihre Daten. RUM bietet mehrere Operatorklassen für verschiedene Anwendungsfälle.

Arten von RUM-Operatorklassen

In der folgenden Tabelle sind die verschiedenen RUM-Operator-Klassen und ihre primären Anwendungsfälle zusammengefasst.

Operator-Klasse Hauptanwendungsfall Beschränkungen
rum_tsvector_ops Standard-Volltextsuche mit Ranking und Suche nach Wortgruppen. –
rum_tsvector_hash_ops Kleinerer Index und schnellere Aktualisierungen für die Volltextsuche. Die Präfixsuche wird nicht unterstützt.
rum_tsvector_addon_ops Volltextsuche, sortiert nach einer anderen Spalte. –
rum_anyarray_ops In Array-Spalten suchen. –
rum_<TYPE>_ops Skalare Typen für entfernungsbasierte Abfragen indexieren. –
rum_tsvector_hash_addon_ops Hash-basierte Volltextsuche, sortiert nach einer anderen Spalte. Präfixabgleich wird nicht unterstützt.
rum_tsquery_ops Gespeicherte tsquery-Werte für die umgekehrte Suche werden indexiert. –
rum_anyarray_addon_ops Array-Suche, sortiert nach einer anderen Spalte. –

Verwenden Sie die Operatorklasse rum_tsvector_ops für die Standardtextsuche, die schnelle Ranking- und Phrasensuchfunktionen erfordert. Diese Operatorklasse speichert die Position jedes Lexems im Index. Im folgenden Beispiel wird eine Tabelle mit dem Namen documents und einer content-Spalte erstellt.

  1. Erstellen Sie eine Tabelle mit dem Namen documents:

    sql CREATE TABLE documents ( id SERIAL PRIMARY KEY, title TEXT NOT NULL, content TEXT NOT NULL, published_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() );

  2. Füllen Sie die Tabelle documents mit Beispieldaten:

    INSERT INTO documents (title, content) VALUES
      ('Title', 'This search engine is working as intended');
    

  3. Fügen Sie Ihrer Tabelle eine generierte tsvector-Spalte hinzu. In dieser Spalte wird der verarbeitete Text automatisch gespeichert und die Abfrageleistung verbessert:

    ALTER TABLE documents
    ADD COLUMN search_vector tsvector
    GENERATED ALWAYS AS (to_tsvector('english', content)) STORED;
    

  4. Erstellen Sie den RUM-Index für die neue Spalte search_vector:

    CREATE INDEX idx_docs_rum
    ON documents
    USING rum (search_vector rum_tsvector_ops);
    

  5. Fragen Sie die Tabelle mithilfe des Index ab. Der Operator <=> berechnet den Relevanzwert oder die Distanz zwischen dem Dokument und der Abfrage direkt aus dem Index, was eine schnelle Sortierung ermöglicht:

    SELECT title, content
    FROM documents
    WHERE search_vector @@ to_tsquery('english', 'search <-> engine')
    ORDER BY search_vector <=> to_tsquery('english', 'search <-> engine');
    

  6. Fügen Sie der Tabelle documents weitere Daten hinzu:

    INSERT INTO documents (title, content) VALUES ('Title1', 'English is my primary language.');
    INSERT INTO documents (title, content) VALUES ('Title2', 'Google has a great engineering culture');
    

  7. Führen Sie eine Suchanfrage mit Präfix aus. Damit werden Dokumente gefunden, die Wörter enthalten, die mit eng beginnen, z. B. engineer oder english:

    SELECT title, content
    FROM documents
    WHERE search_vector @@ to_tsquery('english', 'eng:*');
    

Verwenden Sie die Operatorklasse rum_tsvector_hash_ops, um die Indexgröße zu reduzieren und die Aktualisierungsgeschwindigkeit zu verbessern. In dieser Klasse wird ein Hash jedes Lexems anstelle des vollständigen Lexems gespeichert. Dieser Ansatz führt zu einem kleineren Index, unterstützt jedoch keine Präfixsuche. Im folgenden Beispiel wird davon ausgegangen, dass Sie eine Tabelle mit dem Namen documents und einer search_vector-Spalte haben.

  1. Erstellen Sie den RUM-Index mit der Hash-Operatorklasse:

    CREATE INDEX idx_docs_rum_hash
    ON documents
    USING rum (search_vector rum_tsvector_hash_ops);
    

  2. Fügen Sie der Tabelle documents weitere Daten hinzu:

    INSERT INTO documents (title, content) VALUES ('Title3', 'That person was driving incredibly fast, however the routing was not very efficient');
    

  3. Führen Sie eine Standardabfrage aus:

    SELECT * FROM documents WHERE search_vector @@ to_tsquery('english', 'fast & efficient');
    
    

Index für die Suche, sortiert nach Zeitstempel

Verwenden Sie die Operatorklasse rum_tsvector_addon_ops, um Abfragen zu optimieren, die nach Text filtern und nach einem anderen Feld wie einem Zeitstempel sortieren. Bei diesem Muster wird der Wert des zusätzlichen Felds direkt im Index gespeichert. Dadurch wird ein langsamer Sortiervorgang nach der Suche vermieden. Im folgenden Beispiel wird davon ausgegangen, dass Sie eine Tabelle namens documents mit einer search_vector-Spalte und einer published_at-Spalte haben.

  1. Erstellen Sie einen Index, der den Zeitstempel published_at enthält:

    CREATE INDEX idx_docs_rum_timestamp
    ON documents
    USING rum (search_vector rum_tsvector_addon_ops, published_at)
    WITH (attach = 'published_at', to = 'search_vector');
    

  2. Führen Sie eine Abfrage aus, die Dokumente mit dem Wort engine findet und nach Erscheinungsdatum sortiert. Der Index verarbeitet sowohl die Suche als auch die Sortierung effizient:

    SELECT title, published_at
    FROM documents
    WHERE search_vector @@ to_tsquery('english', 'engine')
    ORDER BY published_at DESC;
    

Verwenden Sie die Operatorklasse rum_anyarray_ops, um Array-Spalten wie eine Liste von Tags zu indexieren. So können Sie effizient nach Arrays suchen, die sich überschneiden (&&), enthalten (@>) oder in anderen Arrays enthalten sind (<@). Im folgenden Beispiel wird der Tabelle documents eine tags-Spalte hinzugefügt.

  1. Fügen Sie eine tags-Spalte hinzu und füllen Sie sie mit Daten:

    ALTER TABLE documents 
    ADD COLUMN tags TEXT[];
    
    INSERT INTO documents (title, content, tags) VALUES ( 'Title4', 'Sample Text', ARRAY['ai', 'ml'] );
    

  2. Erstellen Sie den RUM-Index für eine TEXT[]-Spalte mit dem Namen tags:

    CREATE INDEX idx_tags_rum
    ON documents
    USING rum (tags rum_anyarray_ops);
    

  3. Führen Sie eine Abfrage aus, um Dokumente zu finden, die entweder ai oder ml in ihren Tags enthalten:

    SELECT * FROM documents WHERE tags && '{"ai", "ml"}';
    

Index für skalare Typen

Verwenden Sie die rum_<TYPE>_ops-Operatorklassen, um Spalten mit kontinuierlichen Werten wie Ganzzahlen, Zeitstempeln oder Gleitkommazahlen zu indexieren. Mit diesen Operatorklassen können Sie den Operator <=> verwenden, um die Distanz zwischen Werten effizient zu berechnen. Im folgenden Beispiel wird davon ausgegangen, dass Sie eine Tabelle mit dem Namen documents haben.

  1. Fügen Sie der Tabelle documents eine generische Ganzzahlspalte wie rating hinzu:

    ALTER TABLE documents
    ADD COLUMN rating INT;
    
    UPDATE documents 
    SET rating = floor(random() * 5 + 1);
    

  2. Erstellen Sie einen RUM-Index für die Spalte rating:

    CREATE INDEX idx_rating_rum
    ON documents
    USING rum (rating rum_int4_ops);
    

  3. Führen Sie eine Abfrage aus, um Dokumente mit einem rating zu finden, der dem Wert 5 am nächsten ist:

    SELECT title, rating
    FROM documents
    ORDER BY rating <=> 5;
    

Index für optimierte Hash-Suche, sortiert nach Zeitstempel

Verwenden Sie die Operatorklasse rum_tsvector_hash_addon_ops, um die Vorteile eines Hash-Index mit den Sortierfunktionen eines Add-on-Index zu kombinieren. In dieser Klasse wird ein Hash jedes Lexems zusammen mit dem Wert einer zusätzlichen Spalte gespeichert. Diese Konfiguration unterstützt eine effiziente Sortierung nach der zusätzlichen Spalte, aber keinen Präfixabgleich. Im folgenden Beispiel wird davon ausgegangen, dass Sie eine Tabelle mit dem Namen documents mit einer search_vector-Spalte und einer published_at-Zeitstempelspalte haben.

  1. Erstellen Sie einen RUM-Index, der die Hash-Operatorklasse verwendet und den Zeitstempel published_at enthält:

    CREATE INDEX idx_docs_rum_hash_timestamp
    ON documents
    USING rum (search_vector rum_tsvector_hash_addon_ops, published_at)
    WITH (attach = 'published_at', to = 'search_vector');
    

  2. Führen Sie eine Abfrage aus, die Dokumente mit engine findet und nach Erscheinungsdatum sortiert:

    SELECT title, published_at
    FROM documents
    WHERE search_vector @@ to_tsquery('english', 'engine')
    ORDER BY published_at DESC;
    

Index für gespeicherte Abfragen

Verwenden Sie die Operatorklasse rum_tsquery_ops, um tsquery-Werte zu indexieren. So können Sie eine „umgekehrte Suche“ durchführen und feststellen, welche gespeicherten Abfragen mit einem bestimmten Eingabedokument übereinstimmen. Im folgenden Beispiel wird eine Tabelle mit dem Namen queries erstellt.

  1. Erstellen Sie eine Tabelle zum Speichern von Abfragen:

    sql CREATE TABLE queries ( query_text tsquery ); INSERT INTO queries (query_text) VALUES (plainto_tsquery('AlloyDB is fast!'));

  2. Erstellen Sie einen RUM-Index für die Spalte query_text:

    CREATE INDEX idx_queries_rum
    ON queries
    USING rum (query_text rum_tsquery_ops);
    

  3. Führen Sie eine Abfrage aus, um gespeicherte Abfragen zu finden, die mit einem Dokument übereinstimmen:

    SELECT *
    FROM queries
    WHERE to_tsvector('english', 'AlloyDB is fast') @@ query_text;
    

Index für Array-Suche, sortiert nach Zeitstempel

Verwenden Sie die Operatorklasse rum_anyarray_addon_ops, um Array-Spalten zusammen mit einer zusätzlichen Spalte für die Sortierung zu indexieren. Im folgenden Beispiel wird davon ausgegangen, dass Sie eine Tabelle mit dem Namen documents mit einer tags-Spalte und einer published_at-Zeitstempelspalte haben.

  1. Erstellen Sie einen RUM-Index für die Spalte tags, die den Zeitstempel published_at enthält:

    CREATE INDEX idx_tags_rum_timestamp
    ON documents
    USING rum (tags rum_anyarray_addon_ops, published_at)
    WITH (attach = 'published_at', to = 'tags');
    

  2. Führen Sie eine Abfrage aus, um Dokumente mit dem Tag ai zu finden, sortiert nach Erscheinungsdatum:

    SELECT title, published_at
    FROM documents
    WHERE tags @> '{"ai"}'
    ORDER BY published_at DESC;
    

Nächste Schritte