Membuat dan mengelola indeks RUM

Dokumen ini menunjukkan cara membuat ekstensi RUM dan membuat indeks untuk mengoptimalkan penelusuran teks lengkap di AlloyDB untuk PostgreSQL. Dokumen ini memberikan contoh untuk kasus penggunaan umum, termasuk pemberian peringkat, penelusuran frasa, dan pengurutan menurut stempel waktu.

Sebelum memulai

Untuk membuat ekstensi RUM, Anda harus memiliki peran alloydb_superuser. Untuk mengetahui informasi selengkapnya tentang cara memberikan peran, lihat Menambahkan akun pengguna atau layanan IAM ke cluster.

Buat ekstensi RUM

Anda harus membuat ekstensi RUM sekali per database.

  1. Hubungkan ke database AlloyDB Anda menggunakan psql atau klien lain. Untuk mengetahui informasi selengkapnya, lihat Menghubungkan ke instance cluster.
  2. Jalankan perintah SQL berikut untuk membuat ekstensi:

    CREATE EXTENSION IF NOT EXISTS rum;
    

Membuat indeks RUM

Untuk mengoptimalkan kueri penelusuran teks lengkap, buat indeks RUM pada data Anda. RUM menawarkan beberapa class operator untuk berbagai kasus penggunaan.

Jenis class operator RUM

Tabel berikut merangkum berbagai class operator RUM dan kasus penggunaan utamanya.

Kelas Operator Kasus Penggunaan Utama Batasan
rum_tsvector_ops Penelusuran teks lengkap standar dengan peringkat dan penelusuran frasa. T/A
rum_tsvector_hash_ops Indeks yang lebih kecil dan update yang lebih cepat untuk penelusuran teks lengkap. Tidak mendukung penelusuran awalan.
rum_tsvector_addon_ops Penelusuran teks lengkap diurutkan berdasarkan kolom lain. T/A
rum_anyarray_ops Menelusuri dalam kolom array. T/A
rum_<TYPE>_ops Mengindeks jenis skalar untuk kueri berbasis jarak. T/A
rum_tsvector_hash_addon_ops Penelusuran teks lengkap berbasis hash yang diurutkan berdasarkan kolom lain. Tidak mendukung pencocokan awalan.
rum_tsquery_ops Mengindeks nilai tsquery yang disimpan untuk penelusuran terbalik. T/A
rum_anyarray_addon_ops Penelusuran array diurutkan berdasarkan kolom lain. T/A

Gunakan class operator rum_tsvector_ops untuk penelusuran teks standar yang memerlukan kemampuan penelusuran frasa dan peringkat cepat. Class operator ini menyimpan posisi setiap leksem dalam indeks. Contoh berikut membuat tabel bernama documents dengan kolom content.

  1. Buat tabel bernama documents:

    CREATE TABLE documents (
      id SERIAL PRIMARY KEY,
      title TEXT NOT NULL,
      content TEXT NOT NULL,
      published_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
    );
    
  2. Isi tabel documents dengan data sampel:

    INSERT INTO documents (title, content) VALUES
      ('Title', 'This search engine is working as intended');
    
  3. Tambahkan kolom tsvector yang dihasilkan ke tabel Anda. Kolom ini secara otomatis menyimpan teks yang diproses dan meningkatkan performa kueri:

    ALTER TABLE documents
    ADD COLUMN search_vector tsvector
    GENERATED ALWAYS AS (to_tsvector('english', content)) STORED;
    
  4. Buat indeks RUM di kolom search_vector baru:

    CREATE INDEX idx_docs_rum
    ON documents
    USING rum (search_vector rum_tsvector_ops);
    
  5. Buat kueri tabel menggunakan indeks. Operator <=> menghitung skor relevansi, atau jarak, antara dokumen dan kueri langsung dari indeks, sehingga memungkinkan pengurutan cepat:

    SELECT title, content
    FROM documents
    WHERE search_vector @@ to_tsquery('english', 'search <-> engine')
    ORDER BY search_vector <=> to_tsquery('english', 'search <-> engine');
    
  6. Isi tabel documents dengan lebih banyak data:

    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. Jalankan kueri penelusuran awalan. Ini akan menemukan dokumen yang berisi kata-kata yang diawali dengan eng, seperti engineer atau english:

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

Gunakan class operator rum_tsvector_hash_ops untuk mengurangi ukuran indeks dan meningkatkan kecepatan pembaruan. Class ini menyimpan hash setiap leksem, bukan leksem lengkap. Pendekatan ini menghasilkan indeks yang lebih kecil, tetapi tidak mendukung penelusuran awalan. Contoh berikut mengasumsikan bahwa Anda memiliki tabel bernama documents dengan kolom search_vector.

  1. Buat indeks RUM menggunakan class operator hash:

    CREATE INDEX idx_docs_rum_hash
    ON documents
    USING rum (search_vector rum_tsvector_hash_ops);
    
  2. Isi tabel documents dengan lebih banyak data:

    INSERT INTO documents (title, content) VALUES ('Title3', 'That person was driving incredibly fast, however the routing was not very efficient');
    
  3. Menjalankan kueri pencocokan standar:

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

Indeks untuk penelusuran yang diurutkan berdasarkan stempel waktu

Gunakan class operator rum_tsvector_addon_ops untuk mengoptimalkan kueri yang memfilter menurut teks dan mengurutkan menurut kolom lain, seperti stempel waktu. Pola ini menyimpan nilai kolom tambahan langsung di indeks, sehingga menghindari operasi pengurutan yang lambat setelah penelusuran. Contoh berikut mengasumsikan bahwa Anda memiliki tabel bernama documents dengan kolom search_vector dan kolom published_at.

  1. Buat indeks yang menyertakan stempel waktu published_at:

    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. Jalankan kueri yang menemukan dokumen yang berisi kata engine dan mengurutkannya berdasarkan tanggal publikasi. Indeks menangani penelusuran dan pengurutan secara efisien:

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

Gunakan class operator rum_anyarray_ops untuk mengindeks kolom array, seperti daftar tag. Dengan demikian, Anda dapat membuat kueri secara efisien untuk array yang tumpang-tindih (&&), berisi (@>), atau dimuat oleh (<@) array lain. Contoh berikut menambahkan kolom tags ke tabel documents.

  1. Tambahkan kolom tags dan isi dengan data:

    ALTER TABLE documents 
    ADD COLUMN tags TEXT[];
    
    INSERT INTO documents (title, content, tags) VALUES ( 'Title4', 'Sample Text', ARRAY['ai', 'ml'] );
    
  2. Buat indeks RUM pada kolom TEXT[] bernama tags:

    CREATE INDEX idx_tags_rum
    ON documents
    USING rum (tags rum_anyarray_ops);
    
  3. Jalankan kueri untuk menemukan dokumen yang memiliki ai atau ml dalam tagnya:

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

Indeks untuk jenis skalar

Gunakan class operator rum_<TYPE>_ops untuk mengindeks kolom yang berisi nilai berkelanjutan, seperti bilangan bulat, stempel waktu, atau bilangan floating point. Class operator ini memungkinkan Anda menggunakan operator <=> untuk menghitung jarak antar-nilai secara efisien. Contoh berikut mengasumsikan bahwa Anda memiliki tabel bernama documents.

  1. Tambahkan kolom bilangan bulat umum, seperti rating, ke tabel documents:

    ALTER TABLE documents
    ADD COLUMN rating INT;
    
    UPDATE documents 
    SET rating = floor(random() * 5 + 1);
    
  2. Buat indeks RUM pada kolom rating:

    CREATE INDEX idx_rating_rum
    ON documents
    USING rum (rating rum_int4_ops);
    
  3. Jalankan kueri untuk menemukan dokumen dengan rating yang paling mendekati nilai 5:

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

Indeks untuk penelusuran hash yang dioptimalkan diurutkan berdasarkan stempel waktu

Gunakan class operator rum_tsvector_hash_addon_ops untuk menggabungkan manfaat indeks hash dengan kemampuan pengurutan indeks add-on. Class ini menyimpan hash setiap leksem beserta nilai kolom tambahan. Konfigurasi ini mendukung pengurutan yang efisien menurut kolom tambahan, tetapi tidak mendukung pencocokan awalan. Contoh berikut mengasumsikan bahwa Anda memiliki tabel bernama documents dengan kolom search_vector dan kolom stempel waktu published_at.

  1. Buat indeks RUM yang menggunakan class operator hash dan menyertakan stempel waktu published_at:

    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. Jalankan kueri yang menemukan dokumen yang berisi engine dan mengurutkannya berdasarkan tanggal publikasi:

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

Indeks untuk kueri tersimpan

Gunakan class operator rum_tsquery_ops untuk mengindeks nilai tsquery. Hal ini memungkinkan Anda melakukan "penelusuran terbalik", mengidentifikasi kueri tersimpan mana yang cocok dengan dokumen input tertentu. Contoh berikut membuat tabel bernama queries.

  1. Buat tabel untuk menyimpan kueri:

    CREATE TABLE queries (
    query_text tsquery
    );
    INSERT INTO queries (query_text) VALUES (plainto_tsquery('AlloyDB is fast!'));
    
  2. Buat indeks RUM pada kolom query_text:

    CREATE INDEX idx_queries_rum
    ON queries
    USING rum (query_text rum_tsquery_ops);
    
  3. Jalankan kueri untuk menemukan kueri tersimpan yang cocok dengan dokumen:

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

Indeks untuk penelusuran array yang diurutkan berdasarkan stempel waktu

Gunakan class operator rum_anyarray_addon_ops untuk mengindeks kolom array bersama dengan kolom tambahan untuk pengurutan. Contoh berikut mengasumsikan bahwa Anda memiliki tabel bernama documents dengan kolom tags dan kolom stempel waktu published_at.

  1. Buat indeks RUM pada kolom tags yang menyertakan stempel waktu published_at:

    CREATE INDEX idx_tags_rum_timestamp
    ON documents
    USING rum (tags rum_anyarray_addon_ops, published_at)
    WITH (attach = 'published_at', to = 'tags');
    
  2. Jalankan kueri untuk menemukan dokumen dengan tag ai, yang diurutkan berdasarkan tanggal publikasi:

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

Langkah berikutnya