Włączanie i używanie rozszerzenia DiskANN na serwerze elastycznym Azure Database for PostgreSQL

DiskANN to skalowalny przybliżony algorytm wyszukiwania najbliższych sąsiadów umożliwiający wydajne wyszukiwanie wektorów w dowolnej skali. Oferuje wysoką trafność, dużą liczbę zapytań na sekundę i niskie opóźnienie zapytań, nawet dla zbiorów danych liczących miliardy punktów. Te cechy sprawiają, że jest to zaawansowane narzędzie do obsługi dużych ilości danych.

Aby dowiedzieć się więcej na temat DiskANN, zobacz DiskANN: Wyszukiwanie wektorowe w skali sieci Web i rekomendacje.

Rozszerzenie pg_diskann dodaje obsługę wykorzystywania DiskANN do efektywnego indeksowania i wyszukiwania wektorów.

Włącz pg_diskann

Aby użyć pg_diskann rozszerzenia na serwerze elastycznym Azure Database for PostgreSQL, należy zezwolić na rozszerzenie na poziomie serwera. Następnie należy utworzyć rozszerzenie dla każdej bazy danych, w której chcesz użyć funkcji udostępnianych przez rozszerzenie.

Ponieważ pg_diskann ma zależność od rozszerzenia vector, albo zezwól, albo utwórz rozszerzenie vector w tej samej bazie danych, a następnie uruchom następujące polecenie:

CREATE EXTENSION IF NOT EXISTS pg_diskann;

Możesz też pominąć jawne zezwalanie i tworzenie vector rozszerzenia, a zamiast tego uruchomić poprzednie polecenie dołączając klauzulę CASCADE . Klauzula PostgreSQL automatycznie uruchamia polecenie CREATE EXTENSION dla rozszerzenia, od którego zależy system. W tym celu uruchom następujące polecenie:

CREATE EXTENSION IF NOT EXISTS pg_diskann CASCADE;

Aby usunąć rozszerzenie z bazy danych, do której aktualnie nawiązane połączenie, uruchom następujące polecenie:

DROP EXTENSION IF EXISTS pg_diskann;

Korzystanie z metody dostępu do indeksu diskann

Po zainstalowaniu rozszerzenia można utworzyć diskann indeks w kolumnie tabeli zawierającej dane wektorowe. Aby na przykład utworzyć indeks w embedding kolumnie demo tabeli, użyj następującego polecenia:

CREATE TABLE demo (
 id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
 embedding public.vector(3)
 -- other columns
);

-- insert dummy data
INSERT INTO demo (embedding) VALUES
('[1.0, 2.0, 3.0]'),
('[4.0, 5.0, 6.0]'),
('[7.0, 8.0, 9.0]');

-- create a diskann index by using Cosine distance operator
CREATE INDEX demo_embedding_diskann_idx ON demo USING diskann (embedding vector_cosine_ops)

Po utworzeniu indeksu można uruchamiać zapytania, aby znaleźć najbliższych sąsiadów.

Poniższe zapytanie wyszukuje pięciu najbliższych sąsiadów wektora [2.0, 3.0, 4.0]:

SELECT id, embedding
FROM demo
ORDER BY embedding <=> '[2.0, 3.0, 4.0]'
LIMIT 5;

Usługa Postgres automatycznie decyduje, kiedy używać indeksu DiskANN. Jeśli zdecyduje się nie używać indeksu w scenariuszu, w którym ma używać indeksu, wykonaj następujące polecenie:

-- Explicit Transcation block to force use for DiskANN index.

BEGIN;
SET LOCAL enable_seqscan TO OFF;
-- Similarity search queries
COMMIT;

Ważne

Ustawienie enable_seqscan wartości wyłączonej zniechęca planistę do korzystania z planu skanowania sekwencyjnego przez planistę zapytań, jeśli istnieją inne dostępne metody. Ponieważ jest ona wyłączona za pomocą SET LOCAL polecenia , ustawienie ma zastosowanie tylko dla bieżącej transakcji. Po wykonaniu operacji COMMIT lub ROLLBACK, ustawienie poziomu sesji ponownie wchodzi w życie. Jeśli zapytanie obejmuje inne tabele, ustawienie również zniechęca do korzystania ze skanowania sekwencyjnego we wszystkich z nich.

Wydajne skalowanie przy użyciu kwantyzacji (wersja zapoznawcza)

Funkcja DiskANN używa kwantyzacji produktu (PQ), aby znacznie zmniejszyć zużycie pamięci wektorów. W przeciwieństwie do innych technik kwantyzacji algorytm PQ może bardziej efektywnie kompresować wektory, co znacznie poprawia wydajność.  Korzystając z PQ, diskANN może zachować więcej danych w pamięci, zmniejszyć potrzebę uzyskania dostępu do wolniejszego magazynu i użyć mniejszej mocy obliczeniowej podczas porównywania skompresowanych wektorów. Skutkuje to lepszą wydajnością i znacznymi oszczędnościami kosztów podczas pracy z większymi ilościami danych (> 1 milion wierszy).

Ważne

Obsługa kwantyzacji produktu na serwerze DiskANN jest dostępna od wersji pg_diskann w wersji 0.6 lub nowszej.

Aby zmniejszyć rozmiar indeksu i dopasować więcej danych do pamięci, użyj PQ:

CREATE INDEX demo_embedding_diskann_idx ON demo USING diskann(embedding vector_cosine_ops) 
WITH(
    product_quantized=true
    );    

Zwiększ dokładność podczas korzystania z PQ z wektorowym ponownym rankingowaniem

Ponowne rangowanie z użyciem pełnych wektorów to technika stosowana w systemach wyszukiwania przybliżonych najbliższych sąsiadów (ANN), takich jak DiskANN z kwantyzacją produktu (PQ), w celu zwiększenia dokładności wyników poprzez ponowne uporządkowanie pierwszych N pobranych kandydatów na podstawie oryginalnych, nieskompresowanych wektorów (o pełnej precyzji). Ta technika ponownego rankingowania opiera się wyłącznie na metrykach dokładnego podobieństwa wektorów (na przykład podobieństwie cosinusowym lub odległości euklidesowej). Ta technika nie jest tym samym co ponowne rankingowanie przy użyciu modelu rankingowego.

Aby zrównoważyć szybkość i precyzję wyszukiwania podobnych wektorów, zastosuj dwuetapową strategię ponownego uszeregowania wyników podczas wykonywania zapytań przy użyciu DiskANN i kwantyzacji iloczynowej w celu zwiększenia dokładności.

  1. Wstępne wyszukiwanie przybliżone: Zapytanie wewnętrzne korzysta z algorytmu DiskANN, aby pobrać 50 najlepszych przybliżonych najbliższych sąsiadów na podstawie odległości cosinusowej między zapisanymi embeddingami a wektorem zapytania. Ten krok jest szybki i wydajny, wykorzystując możliwości indeksowania diskANN.

  2. Precyzyjne ponowne rangowanie: Zapytanie zewnętrzne zmienia kolejność tych 50 wyników na podstawie faktycznie obliczonej odległości i zwraca 10 najtrafniejszych wyników:

Oto przykład ponownego rankingowania z zastosowaniem tego dwuetapowego podejścia:

SELECT id
FROM (
    SELECT id, embedding <=> %s::vector AS distance
    FROM demo
    ORDER BY embedding <=> %s::vector asc
    LIMIT 50
) AS t
ORDER BY t.distance
LIMIT 10;

Uwaga / Notatka

Zastąp %s wektorem zapytania. Za pomocą azure_ai można utworzyć wektor zapytania bezpośrednio w usłudze Postgres.

Takie podejście równoważy szybkość (za pośrednictwem przybliżonego wyszukiwania) i dokładności (za pośrednictwem pełnego korbowania wektorowego), zapewniając wysokiej jakości wyniki bez skanowania całego zestawu danych.

Obsługa osadzania o wysokim wymiarze

Zaawansowane aplikacje generatywnej sztucznej inteligencji często opierają się na modelach embeddingowych o wysokiej wymiarowości, takich jak text-embedding-3-large, aby osiągnąć wyższą dokładność. Jednak tradycyjne metody indeksowania, takie jak HNSW w wektorach pgvector , są ograniczone do wektorów z maksymalnie 2000 wymiarami, co ogranicza użycie tych zaawansowanych modeli.

Począwszy od pg_diskann w wersji 0.6 lub nowszej, funkcja DiskANN obsługuje wektory indeksowania z maksymalnie 16 000 wymiarami, co znacznie zwiększa zakres obciążeń sztucznej inteligencji o wysokiej dokładności.

Ważne

Włącz funkcję Product Quantization, aby wykorzystać obsługę danych wysokowymiarowych.

Zalecane ustawienia:

  • product_quantized: Ustaw na wartość true
  • pq_param_num_chunks: ustaw na jedną trzecią wymiaru osadzania, aby uzyskać optymalną wydajność.
  • pq_param_training_samples: Automatycznie określana na podstawie rozmiaru tabeli, chyba że jawnie ustawiono.

To ulepszenie umożliwia skalowalne i wydajne wyszukiwanie w dużych zbiorach danych wektorowych przy zachowaniu wysokiej czułości i precyzji.

Przyspieszanie kompilacji indeksu

Aby poprawić czas kompilacji indeksu, wypróbuj następujące zalecenia.

Korzystanie z większej ilości pamięci

Aby przyspieszyć tworzenie indeksu, zwiększ ilość pamięci przydzielonej na serwerze PostgreSQL na potrzeby kompilacji indeksu. Określ użycie pamięci za pomocą parametru maintenance_work_mem .

-- Set the parameters
SET maintenance_work_mem = '8GB'; -- Depending on your resources

Polecenie CREATE INDEX używa określonej pamięci roboczej, w zależności od dostępnych zasobów, do skompilowania indeksu.

CREATE INDEX demo_embedding_diskann_idx ON demo USING diskann (embedding vector_cosine_ops)

Wskazówka

Zwiększ zasoby pamięci podczas tworzenia indeksu, aby przyspieszyć indeksowanie, a następnie zmniejsz je po zakończeniu indeksowania.

Korzystanie z przetwarzania równoległego

Aby przyspieszyć tworzenie indeksu, użyj równoległych procesów roboczych. Określ liczbę procesów roboczych za pomocą parametru pamięci masowej parallel_workers instrukcji CREATE TABLE podczas tworzenia tabeli. Tę liczbę można później dostosować za pomocą klauzuli SET instrukcji ALTER TABLE.

CREATE TABLE demo (
	id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
	embedding public.vector(3)
) WITH (parallel_workers = 4);
ALTER TABLE demo SET (parallel_workers = 8);

Polecenie CREATE INDEX używa określonej liczby równoległych procesów roboczych, w zależności od dostępnych zasobów, do utworzenia indeksu.

CREATE INDEX demo_embedding_diskann_idx ON demo USING diskann (embedding vector_cosine_ops)

Ważne

Proces główny nie może uczestniczyć w równoległym tworzeniu indeksów.

Jeśli chcesz utworzyć indeks za pomocą równoległych procesów roboczych, ustaw odpowiednio parametry max_parallel_workers, max_worker_processes i max_parallel_maintenance_workers. Aby uzyskać więcej informacji na temat tych parametrów, zobacz parametry kontrolujące użycie zasobów i zachowanie asynchroniczne.

Ustaw te parametry na różnych poziomach szczegółowości. Aby na przykład ustawić je na poziomie sesji, uruchom następujące instrukcje:

-- Set the parameters
SET max_parallel_workers = 8;
SET max_worker_processes = 8; -- Note: Requires server restart
SET max_parallel_maintenance_workers = 4;

Aby dowiedzieć się więcej o innych opcjach konfigurowania tych parametrów na serwerze elastycznym Azure Database for PostgreSQL, zobacz Konfigurowanie parametrów.

Uwaga / Notatka

Parametr max_worker_processes wymaga ponownego uruchomienia serwera, aby zaczęły obowiązywać.

Jeśli konfiguracja tych parametrów i dostępnych zasobów na serwerze nie zezwalają na uruchamianie równoległych procesów roboczych, program PostgreSQL automatycznie wraca do tworzenia indeksu w trybie nieparallelowym.

Parametry konfiguracji

Podczas tworzenia indeksu diskann określ różne parametry, aby kontrolować jego zachowanie.

Parametry indeksu

  • max_neighbors: Maksymalna liczba krawędzi na węzeł na wykresie. Wartość domyślna to 32. Wyższa wartość może poprawić przypominanie do pewnego punktu.
  • l_value_ib: rozmiar listy wyszukiwania podczas kompilacji indeksu. Wartość domyślna to 100. Wyższa wartość sprawia, że kompilacja jest wolniejsza, ale indeks jest o wyższej jakości.
  • product_quantized: umożliwia kwantyzację produktu w celu bardziej wydajnego wyszukiwania. Wartość domyślna to fałsz.
  • pq_param_num_chunks: Liczba fragmentów kwantyzacji produktu. Wartość domyślna to 0, co oznacza, że system automatycznie określa wartość na podstawie osadzonych wymiarów. Użyj jednej trzeciej oryginalnych wymiarów osadzania.
  • pq_param_training_samples: Liczba wektorów używanych do trenowania tabeli pivotów PQ. Wartość domyślna to 0, co oznacza, że system automatycznie określa wartość na podstawie rozmiaru tabeli.
CREATE INDEX demo_embedding_diskann_custom_idx ON demo USING diskann (embedding vector_cosine_ops)
WITH (
 max_neighbors = 48,
 l_value_ib = 100,
 product_quantized=true, 
 pq_param_num_chunks = 0,
 pq_param_training_samples = 0
 );

Parametry rozszerzenia

  • diskann.iterative_search: steruje zachowaniem wyszukiwania.

    Konfiguracje dla programu diskann.iterative_search:

    • relaxed_order (ustawienie domyślne): Umożliwia iteracyjne przeszukiwanie wykresu w partiach diskann.l_value_is, aż do osiągnięcia żądanej liczby krotek, która może być ograniczona przez klauzulę LIMIT. Ta opcja może spowodować, że wyniki będą wyświetlane w niewłaściwej kolejności.

    • strict_order: Podobny do relaxed_order, ale gwarantuje, że wyniki są zwracane w ścisłej kolejności posortowanej według odległości.

    • off: używa funkcji wyszukiwania nieteratywnego. Próbuje pobrać diskann.l_value_is krotki w jednym kroku. Wyszukiwanie nieteratywne może zwracać co najwyżej diskann.l_value_is wektorów dla zapytania, niezależnie od klauzuli zapytania czy liczby krotek pasujących do zapytania.

    Aby zmienić zachowanie strict_order wyszukiwania dla wszystkich zapytań wykonywanych w bieżącej sesji, uruchom następującą instrukcję:

    SET diskann.iterative_search TO 'strict_order';
    

    Aby ją zmienić tak, aby dotyczyła tylko wszystkich zapytań wykonywanych w bieżącej transakcji, uruchom następującą instrukcję:

    BEGIN;
    SET LOCAL diskann.iterative_search TO 'strict_order';
    -- All your queries
    COMMIT;
    
  • diskann.l_value_is: wartość L na potrzeby skanowania indeksów (domyślnie to 100). Zwiększenie wartości poprawia przywołanie, ale może spowolnić wykonywanie zapytań.

    Aby zmienić wartość L skanowania indeksu na 20 dla wszystkich zapytań wykonanych w bieżącej sesji, uruchom następującą instrukcję:

    SET diskann.l_value_is TO 20;
    

    Aby ją zmienić tak, aby dotyczyła tylko wszystkich zapytań wykonywanych w bieżącej transakcji, uruchom następującą instrukcję:

    BEGIN;
    SET LOCAL diskann.l_value_is TO 20;
    -- All your queries
    COMMIT;
    
Rozmiar zestawu danych (wiersze) Typ parametru Name Zalecana wartość
<1 mln Budowanie indeksu l_value_ib 100
<1 mln Budowanie indeksu max_neighbors 32
<1 mln Czas zapytania diskann.l_value_is 100
 
1M-50M Budowanie indeksu l_value_ib 100
1M-50M Budowanie indeksu max_neighbors 64
1M-50M Budowanie indeksu product_quantized true
1M-50M Czas zapytania diskann.l_value_is 100
 
>50 mln Budowanie indeksu l_value_ib 100
>50 mln Budowanie indeksu max_neighbors 96
>50 mln Budowanie indeksu product_quantized true
>50 mln Czas zapytania diskann.l_value_is 100

Uwaga / Notatka

Te parametry mogą się różnić w zależności od określonego zestawu danych i przypadku użycia. Może być konieczne eksperymentowanie z różnymi wartościami parametrów, aby znaleźć optymalne ustawienia dla danego scenariusza.

Postęp operacji CREATE INDEX i REINDEX

Począwszy od bazy danych PostgreSQL 12, możesz użyć pg_stat_progress_create_index polecenia , aby sprawdzić postęp operacji CREATE INDEX lub REINDEX.

SELECT phase, round(100.0 * blocks_done / nullif(blocks_total, 0), 1) AS "%" FROM pg_stat_progress_create_index;

Aby dowiedzieć się więcej na temat możliwych faz, za pomocą których przechodzi operacja CREATE INDEX lub REINDEX, zobacz CREATE INDEX phases (FAZY TWORZENIA INDEKSU).

Wybieranie funkcji dostępu do indeksu

Typ wektora obsługuje trzy typy wyszukiwań w przechowywanych wektorach. Wybierz prawidłową funkcję dostępu dla indeksu, aby baza danych mogła rozważyć indeks podczas wykonywania zapytań.

pg_diskann obsługuje następujące operatory odległości:

  • vector_l2_ops: <-> Odległość euklidesowa
  • vector_cosine_ops: <=> Odległość kosinusowa
  • vector_ip_ops: <#> Produkt wewnętrzny

Rozwiązywanie problemów

Błąd: : assertion left == right failed left: 40 right: 0

  • Wersja GA DiskANN, v0.6.x wprowadza zmiany niekompatybilne w formacie metadanych indeksu. Indeksy utworzone za pomocą wersji 0.5.x nie są zgodne z operacjami wstawiania w wersji 0.6.x. Jeśli spróbujesz wstawić do tabeli z nieaktualnym indeksem, wystąpi błąd, nawet jeśli indeks jest prawidłowy.

  • Jeśli wystąpi ten błąd, rozwiąż go, wykonując następujące czynności:

    • Opcja 1: Wykonanie instrukcji REINDEX lub REDINDEX CONCURRENTLY w indeksie.

    • Opcja 2: Ponowne kompilowanie indeksu.

      DROP INDEX your_index_name;
      CREATE INDEX your_index_name ON your_table USING diskann(your_vector_column vector_cosine_ops);
      
      

Błąd: : diskann index needs to be upgraded to version 2...

  • Gdy wystąpi ten błąd, rozwiąż go w następujący sposób:
    • Opcja 1: Wykonanie instrukcji REINDEX lub REDINDEX CONCURRENTLY w indeksie.

    • Opcja 2: Ze względu REINDEX na to, że rozszerzenie może zająć dużo czasu, udostępnia również funkcję zdefiniowaną przez użytkownika o nazwie upgrade_diskann_index(), która uaktualnia indeks szybciej, gdy jest to możliwe.

      Aby uaktualnić indeks, uruchom następującą instrukcję:

      SELECT upgrade_diskann_index('demo_embedding_diskann_custom_idx');
      

      Aby uaktualnić wszystkie indeksy diskann w bazie danych do bieżącej wersji, uruchom następującą instrukcję:

      SELECT upgrade_diskann_index(pg_class.oid)
      FROM pg_class
      JOIN pg_am ON (pg_class.relam = pg_am.oid)
      WHERE pg_am.amname = 'diskann';