본문 바로가기
카테고리 없음

pgvector 0.8.7 보안 수정이 나온 뒤 IVFFlat과 HNSW 인덱스를 고르는 기준

by Juelria 2026. 10. 27.
728x90
반응형
SMALL

pgvector 0.8.7이 2026년 10월 1일에 나왔어요. IVFFlat 인덱스를 만드는 과정의 버퍼 오버플로를 고친 버전이고, 이슈에는 IVFFlat 인덱스를 만들 수 있는 데이터베이스 사용자가 범위 밖 메모리에 쓸 수 있어 임의 코드 실행으로 이어질 수 있다고 적혀 있어요. Postgres에 임베딩을 넣어 RAG 검색을 하고 있다면 버전부터 보고, 이 기회에 인덱스 종류가 지금 데이터에 맞는지도 점검해 볼 만해요.

0.8.7에서 확인한 내용

pgvector 저장소의 CHANGELOG에는 0.8.7(2026-10-01) 항목이 두 줄이에요. IVFFlat 인덱스 빌드의 버퍼 오버플로 수정, 그리고 조건에 맞는 행이 없을 때 avg 집계에서 나던 오류 수정이에요. 이슈 번호는 #1036이고 영향받는 버전은 0.8.6 이하, 고쳐진 버전은 0.8.7이라고 적혀 있어요. 이슈에는 CVE-2026-103484라는 번호도 붙어 있어요.

7월 29일에 나온 0.8.6도 IVFFlat 빌드의 버퍼 오버플로를 고쳤는데, 그쪽은 32비트 시스템 이야기였어요. 두 번 연속 같은 빌드 경로가 고쳐졌으니 0.8.5 이하에서 멈춰 있다면 올릴 이유가 분명해요. 참고로 CHANGELOG 맨 위의 0.9.0은 아직 미출시로 적혀 있어서, 지금 올릴 수 있는 최신은 0.8.7이에요.

버전 확인과 업그레이드 순서

내 데이터베이스에 설치된 버전은 이 쿼리로 볼 수 있어요.

SELECT extversion FROM pg_extension WHERE extname = 'vector';

올릴 때는 처음 설치한 방식 그대로 최신 버전을 설치한 다음, 업그레이드할 데이터베이스마다 ALTER EXTENSION vector UPDATE;를 실행하라고 README가 안내해요. 데이터베이스가 여럿이면 하나씩 해야 하는 점을 놓치기 쉬워요. 관리형 Postgres를 쓴다면 서비스가 제공하는 pgvector 버전은 제공 업체 문서에서 따로 확인하세요.

IVFFlat과 HNSW는 이렇게 달라요

README의 설명을 줄이면 이래요. HNSW는 다층 그래프로, 속도와 재현율의 균형이 IVFFlat보다 좋지만 빌드가 느리고 메모리를 더 써요. 대신 훈련 단계가 없어서 테이블이 비어 있어도 만들 수 있어요. IVFFlat은 벡터를 여러 리스트로 나눠 가까운 리스트 일부만 찾아요. 빌드가 빠르고 메모리를 덜 쓰지만 검색 품질은 낮은 편이에요.

설정값도 달라요. HNSW는 m(기본 16)과 ef_construction(기본 64)으로 만들고, 검색할 때는 hnsw.ef_search(기본 40)를 올려 재현율을 높여요. IVFFlat은 lists를 정해 만들고, 검색 때 ivfflat.probes(기본 1)를 조절해요. README는 IVFFlat을 데이터가 어느 정도 들어간 뒤에 만들고, lists는 100만 행까지는 행 수를 1000으로 나눈 값, 그 이상은 행 수의 제곱근에서 시작하라고 해요. probes는 lists의 제곱근에서 시작하면 돼요.

우리 데이터에 맞춰 고르기

문서 조각이 50만 개쯤 쌓인 RAG 테이블이라고 해 볼게요. IVFFlat이라면 50만을 1000으로 나눈 500이 lists의 출발점이고, probes는 500의 제곱근인 22 안팎에서 시작해요. 이 숫자는 README 공식에 대입한 계산이라서 실제 재현율은 내 데이터로 재 봐야 해요. 인덱스를 지운 기본 검색이 정확한 최근접 검색이니, 같은 질문 몇십 개를 인덱스 있을 때와 없을 때 돌려 상위 결과가 얼마나 겹치는지 비교하면 기준이 생겨요.

문서가 계속 들어오고 처음에는 테이블이 거의 비어 있다면 HNSW가 편해요. README도 HNSW는 훈련 단계가 없어서 데이터가 없는 테이블에도 만들 수 있다고 해요. 반대로 IVFFlat을 데이터가 적은 시점에 만들었다면 결과가 적게 나올 수 있다고 README가 경고해요. 그럴 땐 인덱스를 지우고 데이터가 더 쌓인 뒤에 다시 만들면 돼요. 메모리가 빠듯하거나 빌드 시간이 문제라면 IVFFlat이 부담이 덜해요.

차원도 확인하세요. 인덱스를 만들 수 있는 한도는 vector 2,000차원, halfvec 4,000차원이에요. 임베딩이 3,072차원이라면 embedding::halfvec(3072)로 캐스팅한 표현식 인덱스를 만들고 쿼리에도 같은 캐스팅을 써야 해요. 운영 중인 테이블에는 CREATE INDEX CONCURRENTLY로 만들어야 쓰기가 막히지 않아요.

인덱스를 바꾼 뒤 결과가 줄어들 때

필터를 함께 쓰는 검색에서 결과가 기대보다 적게 나오는 일이 흔해요. 근사 인덱스는 인덱스를 먼저 훑고 나서 조건을 적용하기 때문이에요. README 예시처럼 조건에 맞는 행이 10%뿐이고 hnsw.ef_search가 기본 40이면, 평균 4건만 남아요. 0.8.0부터 쓸 수 있는 반복 스캔을 켜면 필요한 만큼 결과가 모일 때까지 인덱스를 더 훑어요.

SET hnsw.iterative_scan = relaxed_order;

relaxed_order는 결과 순서가 거리 순서에서 약간 어긋날 수 있는 대신 재현율이 좋아요. 순서가 엄격해야 하는 화면이라면 strict_order를 쓰세요. IVFFlat은 ivfflat.iterative_scan으로 설정해요. 필터가 자주 쓰이는 컬럼이 정해져 있다면 그 조건을 붙인 부분 인덱스도 README가 소개하는 방법이에요.

참고한 자료

728x90
반응형
LIST