Eu tenho uma tabela como abaixo no postgres:
create table posts (
id bigserial,
tags text[],
content text,
content_embedding vector(512)
);
create index on posts using GIN(tags);
-- from pgvector
create index ON posts USING hnsw(content_embedding vector_cosine_ops) WITH (m = 24, ef_construction = 100);
Cada linha é basicamente uma postagem em um blog com content
armazenamento de seu texto, tags é uma matriz de tags (por exemplo '{"database","coding"}'
), content_embedding
é onde armazeno uma representação vetorial content
gerada com algum modelo de IA que espero usar para pesquisa semântica.
Quero executar consultas como abaixo para obter postagens que tags
contenham database
or hobby
e ordená-las de acordo com o quão "semelhantes" elas são a um determinado vetor ( '[...]'
abaixo por uma questão de brevidade):
select id, (content_embedding <=> '[...]') as cosine_similarity from posts where tags && '{"database","hobby"}' ORDER BY cosine_distance ASC
No entanto, parece que o plano de consulta explain analyze
não faz uso do índice vetorial, como espero
Sort (cost=8081.77..8089.15 rows=2952 width=16) (actual time=10.444..10.445 rows=20 loops=1)
Sort Key: ((content_embedding <=> '[...]'::vector))
Sort Method: quicksort Memory: 26kB
-> Bitmap Heap Scan on posts (cost=1698.88..7911.62 rows=2952 width=16) (actual time=9.966..10.424 rows=20 loops=1)
Recheck Cond: (tags && '{database,hobby}'::text[])
Heap Blocks: exact=19
-> Bitmap Index Scan on posts_tags_idx (cost=0.00..1698.14 rows=2952 width=0) (actual time=9.842..9.842 rows=20 loops=1)
Index Cond: (tags && '{database,hobby}'::text[])
Planning Time: 0.536 ms
Execution Time: 10.496 ms
Quando removo a where
cláusula, vejo uma varredura de índice sendo usada para classificação
Index Scan using posts_content_embedding_idx on posts (cost=164.90..41510.78 rows=301590 width=16)
Order By: (content_embedding <=> '[...]'::vector)
Eu tenho cerca de 300.000 linhas em posts
. Isso é um fator? Existe uma maneira do postgres usar os índices gin e hnsw? Se não for possível, quantas linhas é o limite antes que minha consulta demore muito (> 100 ms)?
Estou ciente de que existem soluções criadas para esse caso de uso de pesquisa, como Elasticsearch ou talvez bancos de dados vetoriais, mas já tenho um banco de dados postgres e espero poder estendê-lo o máximo que puder.