Лого на 91. НЕГ „Проф. Константин Гълъбов“

Избираем модул · Урок 10

Индекси за търсене по близост

Защо пълното обхождане не мащабира, как приблизителното търсене печели скорост срещу точност и как се мери загубеното.

Проблемът с растежа

Заявката от миналия урок работи, но обхожда всички редове. При 500 парчета това е незабележимо; при 5 милиона всяка заявка сравнява 5 милиона вектора по 384 числа.

пълно обхожданеиндекссравнява с всеки векторгледа само близките области
Индексът разделя пространството предварително и при търсене гледа само няколко области.

Точно срещу приблизително

Приблизително търсене на най-близки (ANN)

Метод, който намира почти винаги най-близките вектори, но не гарантира това — срещу многократно по-висока скорост.

Пълно обхожданеИндекс (ANN)
Резултатточно най-близкитепочти винаги най-близките
Скорост при 1 млнсекундимилисекунди
Паметсамо даннитеданни + структура
Строененямаотнема време при вмъкване
Когадо няколко десетки хилядинад това

Компромисът е настройваем

Всеки такъв индекс има настройка „колко области да провери“. Повече области → по-точно и по-бавно. Стойността се избира с измерване, а не наизуст.

Двата вида индекс в pgvector

IVFFlat — разделяне на области

Векторите се групират в клъстери (спомнете си клъстеризацията от 11. клас). При търсене се проверяват само най-близките няколко клъстера.

CREATE INDEX ON parcheta USING ivfflat (vektor vector_cosine_ops)
WITH (lists = 100);

SET ivfflat.probes = 10;   -- колко области да се проверят при търсене
  • Строи се бързо и заема малко памет.
  • Изисква вече наличиви данни — строи се СЛЕД зареждането.
  • Ориентир: lists ≈ корен квадратен от броя редове.

HNSW — граф от съседи

Изгражда многослоен граф, в който търсенето „скача“ от връх на връх към все по-близки вектори.

CREATE INDEX ON parcheta USING hnsw (vektor vector_cosine_ops);

SET hnsw.ef_search = 60;   -- по-голямо = по-точно и по-бавно
  • По-точен и по-бърз при търсене от IVFFlat.
  • Строи се по-бавно и заема повече памет.
  • Работи и при постепенно добавяне на данни.

Как се мери загубеното

Приблизителният индекс може мълчаливо да пропуска резултати. Проверката е проста: сравняваме с пълното обхождане.

  1. Вземаме 50 реални заявки.
  2. За всяка намираме точния отговор с пълно обхождане (без индекс).
  3. Пускаме същите заявки с индекса.
  4. Мерим каква част от точните резултати се появяват — това е recall@k.
  5. Ако е под приемливото, вдигаме настройката за брой проверени области и мерим отново скоростта.

Индексът не се слага „за всеки случай“

При 2000 парчета индексът може дори да забави заявката и със сигурност добавя риск от пропуснати резултати. Слага се, когато измерите, че пълното обхождане е твърде бавно.