6P by GN⁺ 13시간전 | ★ favorite | 댓글 3개
  • Postgres 확장 pgvector는 벡터 유사도 검색을 지원하지만, 데모 수준과 실제 운영 환경 간의 격차가 큼
  • IVFFlat과 HNSW 인덱스 모두 장단점이 뚜렷하며, 특히 HNSW는 인덱스 생성 시 수 GB 단위의 메모리 사용과 긴 빌드 시간이 문제
  • 실시간 검색 및 인덱스 갱신은 구조적으로 어렵고, 지속적인 삽입·갱신 시 락 경합과 성능 저하 발생
  • 필터링 전략(Pre/Post) 과 쿼리 플래너의 한계로 인해 검색 정확도와 속도 간의 불안정한 균형이 나타남
  • 전용 벡터 데이터베이스(Pinecone, Weaviate 등) 가 제공하는 기능을 수동으로 구현해야 하며, 결과적으로 운영 복잡성과 비용 증가로 이어짐

pgvector의 한계 개요

  • pgvector는 Postgres에 벡터 유사도 검색 기능을 추가하는 확장이며, 단순한 데모에서는 잘 작동하지만 운영 환경에서는 확장성 문제가 발생
  • 많은 블로그 글이 설치와 간단한 쿼리 예시만 다루며, 운영 시 발생하는 성능·메모리·인덱스 관리 문제는 거의 언급하지 않음

인덱스 선택의 문제

  • pgvector는 IVFFlatHNSW 두 가지 인덱스 유형을 제공
    • IVFFlat: 클러스터 기반 구조로, 인덱스 생성 속도는 빠르지만 클러스터 수 설정이 성능과 정확도에 큰 영향을 미침
      • 클러스터 재분배가 불가능해 정기적인 인덱스 재구축 필요
    • HNSW: 다층 그래프 구조로 정확도와 일관된 성능을 제공하지만, 인덱스 생성 시 메모리 사용량이 매우 높고 속도가 느림
  • 수백만 개 벡터 인덱스 생성 시 10GB 이상 RAM 사용 가능성이 있으며, 이는 운영 DB의 안정성에 직접적인 위협

실시간 검색의 어려움

  • 새 데이터 삽입 후 즉시 검색 가능해야 하지만, 인덱스 갱신 구조상 실시간 반영이 어려움
    • IVFFlat: 새 벡터가 기존 클러스터에 추가되며, 시간이 지날수록 클러스터 불균형 발생 → 주기적 재빌드 필요
    • HNSW: 삽입 시 그래프 갱신으로 락 경합 및 메모리 부하 발생
  • 인덱스 재구축 중에는 데이터 일관성 유지와 서비스 지속성 확보가 어려움
  • 운영 환경에서는 스테이징 테이블, 이중 인덱스, 오프라인 빌드, eventual consistency 등 다양한 우회 전략이 필요

필터링과 쿼리 플래너의 한계

  • status, user_id, category메타데이터 필터링과 벡터 검색을 결합할 때 Pre-filter vs Post-filter 선택이 성능에 큰 영향
    • Pre-filter는 선택적 필터에 유리하지만, 데이터가 많을 경우 느림
    • Post-filter는 빠르지만 필터 후 결과 누락 가능성 존재
  • Postgres의 쿼리 플래너는 벡터 유사도 비용 모델을 이해하지 못함, 통계 정보가 부정확해 비효율적 실행 계획 생성
  • 결과적으로 CTE, 파티셔닝, 쿼리 재작성 등 임시 방편적 해결책이 필요하며, 이는 규모 확장 시 비효율적

전용 벡터 데이터베이스와의 비교

  • Pinecone, Weaviate, OpenSearch k-NN 등은 필터링 전략 자동 선택, 하이브리드 검색, 실시간 인덱싱, 수평 확장을 기본 제공
  • pgvector에서는 이러한 기능을 직접 구현해야 하며, 이는 운영 복잡성과 유지보수 부담으로 이어짐
  • Timescale의 pgvectorscale은 StreamingDiskANN, 증분 인덱스 빌드, 필터링 개선 등을 제공하지만,
    • AWS RDS에서는 미지원이며, 추가 확장 설치 및 관리 부담 존재

비용과 운영 고려

  • 전용 벡터 DB는 유료 서비스이지만, Postgres 인프라 과다 프로비저닝·인덱스 관리·엔지니어링 시간을 고려하면 실질적으로 더 저렴할 수 있음
  • 예시로 Turbopuffer는 월 $64부터 시작하며, 운영 단순성과 확장성을 제공

결론 및 권장 사항

  • pgvector는 기술적으로 훌륭하지만 운영 환경에서는 제약이 많음
  • 운영 시스템 구축 시 고려해야 할 핵심 사항
    1. 인덱스 관리의 복잡성과 높은 메모리 요구
    2. 쿼리 플래너의 한계로 인한 필터링 비효율
    3. 실시간 인덱싱의 비용과 품질 저하
    4. 블로그 자료의 과도한 단순화
    5. 전용 벡터 DB의 존재 이유와 그 효율성
  • 결론적으로, Postgres 통합의 단순함보다 운영 복잡성이 더 크며, 대부분의 팀은 전용 벡터 데이터베이스 사용이 현실적 선택

생태계가 건강해지려면 만능썰에 대한 반박도 많아야 한다고 봅니다.

맞죠. 완벽한 것은 없으니까요. "다른 시급한 일이 있다" 정도는 괜찮아도 "현재 수준도 충분하다" 를 용납하면 안 된다고 생각합니다.

Hacker News 의견
  • 우리는 Discourse에서 이미 수천 개의 데이터베이스에 pgvector를 프로덕션 환경에서 사용 중임
    대부분의 페이지뷰에 활용되고 있으며, Iterative Scans 기능은 버전 0.8.0에서 추가되어 pre/post 필터링 문제를 개선했음
    단일 서비스라면 전용 벡터 DB가 더 쉬울 수도 있지만, 그것이 만능 해결책은 아님

    • 우리는 quantization을 적극적으로 사용함
      저장에는 halfvec(16bit float), 인덱스에는 bit(binary vectors)를 사용하여 저장 비용과 성능을 모두 확보했음
    • 우리 회사 Halcyon에서는 수조 개의 임베딩을 다루는데, Postgres는 그 규모에 적합하지 않았음
      Vespa를 사용해 노드 단위로 map-reduce 방식의 검색을 수행함
      Postgres에서 비슷한 걸 하려면 샤딩과 복잡한 애플리케이션 로직이 필요할 것 같음
      재인덱싱이나 메타데이터 비정규화는 시간이 오래 걸릴 수밖에 없다고 봄
      그래도 벡터 DB가 만능은 아니며, Vespa처럼 관계형 필터링을 지원하는 시스템이 훨씬 효율적임
    • pgvector를 프로덕션에서 쓰는 사람은 많음
      하지만 iterative scan은 근본적인 해결책이 아니라 임시방편에 가까움
      ef_search, max_search_tuples 같은 파라미터를 이해해야 하고, planner가 필터링된 벡터 검색의 비용 모델을 완전히 이해하지 못함
      결국 스마트한 쿼리 플래너를 직접 튜닝할 여력이 있는지, 아니면 그걸 전문적으로 다루는 서비스를 쓸지의 문제임
    • 필터링을 인덱스 탐색 중에 수행하는 접근도 있음
      Microsoft의 논문에서 설명된 방법을 Timescale의 pgvectorscale이 구현함
      이 방식은 단순 pre/post 필터링보다 효율적일 수 있음
    • 어떤 용도로 쓰는지 궁금함. 혹시 키워드 + 벡터를 결합한 하이브리드 검색 시스템인가 궁금함
  • 우리는 VectorChord에서 블로그에서 언급된 pgvector의 대부분의 문제를 해결했음
    IVF + quantization을 사용해 pgvector의 HNSW보다 15배 빠른 업데이트를 지원함
    16vCPU, 32GB 메모리로 1억 개의 768차원 벡터를 20분 만에 인덱싱 가능함
    CREATE INDEX CONCURRENTLY로 데이터 손실 없이 재인덱싱 가능함
    pre/post 필터링과 BM25 기반 하이브리드 검색도 지원함
    자세한 내용은 VectorChord 블로그 참고

    • quantization과 IVF를 쓴다면 실제 recall 수치가 어떤지 궁금함
    • 우리는 Postgres + VectorChord + 샤딩으로 30억 개 벡터를 운영 중인 고객이 있음
      관련 사례는 이 블로그에서 확인 가능함
    • VectorChord를 검토했지만 RDS에서 지원되지 않아 별도 서비스를 추가해야 해서 도입하지 못했음
  • 인덱스 빌드는 메모리를 많이 쓰지만, maintenance_work_mem으로 제어 가능함
    인덱스 재빌드는 REINDEX CONCURRENTLY로 처리 가능하고, HNSW 업데이트는 B+tree 업데이트와 비슷한 개념임
    이 글은 Postgres 문서를 제대로 읽지 않은 듯한 인상임

    • 하지만 maintenance_work_mem을 제한하면 인덱싱이 느려짐
      B+tree는 log H 페이지만 건드리지만, HNSW는 수천 개 벡터를 수정해야 함
    • HNSW 인덱스는 수백 GB~수 TB 크기일 수 있음
      이걸 재빌드하려면 DB 용량을 두 배 이상 확보해야 하고, 다른 워크로드에도 영향을 줌
      REINDEX CONCURRENTLY도 시간이 오래 걸림
      HNSW 삽입은 복잡도가 낮더라도 상수 비용이 커서 실제로는 부담이 큼
    • maintenance_work_mem 같은 설정이 있어도 운영 중에 GB 단위 RAM을 몇 시간씩 점유하는 건 위험함
      REINDEX CONCURRENTLY도 디스크를 2~3배 더 쓰고 성능에 영향이 있음
      결국 Postgres 기능이 부족한 게 아니라, 운영 복잡도가 크다는 게 핵심임
      전용 벡터 DB는 이런 걸 자동으로 처리하므로, 작은 팀이라면 훨씬 효율적임
  • Turbopuffer가 월 $64부터 시작한다는 점이 pgvector의 인기를 설명해줌
    $64가 비싸게 느껴지면 pgvector를 쓰면 되고, 싸게 느껴진다면 이미 복잡한 사용 사례라 전용 벡터 DB가 더 적합함

  • GCP 고객 중에서도 pgvector HNSW를 프로덕션에서 쓰는 사례를 많이 봤음
    다만 0~1천만 벡터 규모에서만 현실적임
    ETL, 운영 오버헤드, 일관성 문제 등을 고려해야 함
    트랜잭션, 하이브리드 검색, 저지연이 필요하다면 AlloyDB + ScaNN이 더 나은 선택임
    (참고로 나는 GCP에서 ScaNN을 만들었고 현재 AlloyDB Semantic Search를 이끌고 있음)

    • AlloyDB는 오픈소스가 아니므로 다른 시장을 겨냥한 제품임
  • 내 기본 원칙은 YAGNI
    가능한 한 서비스 수를 줄이고, 문제가 생기면 그때 새로운 걸 추가함
    Postgres로 충분하면 그대로 쓰고, 안 되면 그때 필요한 걸 정확히 알게 됨

    • 하지만 이런 접근은 종종 역효과를 냄
      실시간 벡터 쓰기, SQL 필터와 유사도 검색의 결합 같은 건 사소해 보이지만 실제로는 필수 기능임
      규모가 커지면 이런 제약이 치명적으로 드러남
    • 데이터베이스는 한 번 선택하면 교체가 어렵기 때문에, 처음부터 신중해야 함
  • 벡터 임베딩 모델을 쓸 때는 대규모 데이터셋이 아니더라도 쓸모가 많음
    예를 들어 문서 검색이나 제품 정보 검색 같은 경우임
    나는 파일 시스템처럼 문서를 쓰면 자동으로 인덱스가 갱신되는 인터페이스를 원함
    그래서 Amazon S3 Vectors(링크) 같은 서비스가 흥미로움
    실제 사용 경험이 궁금함

  • 언급된 문제들은 이미 해결되었고, 나는 PGVector 사용을 선호함
    Postgres가 Kafka를 대체해 초당 10만 이벤트를 처리할 수 있다면, Chroma 같은 전용 벡터 DB 대신 PGVector도 충분히 가능함
    참고 링크

    • 구체적으로 어떤 문제들이 해결되었는지 궁금함
  • 대부분의 pgvector 사용 사례는 “기술 문서 기반 챗봇” 같은 소규모 데이터셋임
    데이터가 자주 바뀌지 않고, 멀티테넌시가 없어서 필터링 문제도 적음
    반면 Chroma는 SPANN, SPFresh, 하이브리드 검색을 지원하며 완전한 Apache 2.0 오픈소스
    사용량 기반 요금제로 월 1달러 수준의 비용으로도 가능함

  • 내가 지난 1년간 개발한 Redis Vector Sets는 이런 문제들을 해결함
    HNSW를 직접 구현해 실시간 업데이트가 가능하고, 삭제 시 메모리도 즉시 회수됨
    수십만 ops/sec 삽입, 5만 ops/sec 검색 속도를 지원함
    기본적으로 quantization을 지원해 메모리 효율도 높음
    README 문서에 자세히 정리했음
    현재는 복제 기능도 완전히 테스트 완료됨