Проблемът с растежа
Заявката от миналия урок работи, но обхожда всички редове. При 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.
- Строи се по-бавно и заема повече памет.
- Работи и при постепенно добавяне на данни.
Как се мери загубеното
Приблизителният индекс може мълчаливо да пропуска резултати. Проверката е проста: сравняваме с пълното обхождане.
- Вземаме 50 реални заявки.
- За всяка намираме точния отговор с пълно обхождане (без индекс).
- Пускаме същите заявки с индекса.
- Мерим каква част от точните резултати се появяват — това е recall@k.
- Ако е под приемливото, вдигаме настройката за брой проверени области и мерим отново скоростта.
Индексът не се слага „за всеки случай“
При 2000 парчета индексът може дори да забави заявката и със сигурност добавя риск от пропуснати резултати. Слага се, когато измерите, че пълното обхождане е твърде бавно.