turbopuffer, ANN 벡터 인덱스를 보조 인덱스로 내리는 v3 저장 구조 공개
- turbopuffer가 v3에서 ANN 벡터 인덱스를 주 인덱스에서 보조 인덱스로 내리고, 자동 생성되는 내부 ID인 (segment ID, doc ID)를 새 주 인덱스로 삼는 저장 구조 개편을 진행 중임
- v1은 ID와 벡터만 저장하는 서버리스 벡터 DB로 출발해 그래프 인덱스 대신 SPANN을 쓰고 증분 인덱싱을 위해 SPFresh로 옮겼으며, 객체 스토리지를 진실 원천으로 두고 NVMe SSD와 메모리 계층 캐시로 성능을 확보해 Cursor와 Notion을 초기 고객으로 확보함
- v2에서 속성 필터링용 역색인과 BM25 전문 검색을 추가했지만 모든 인덱스가 ClusterId와 LocalId로 이루어진 ANN 주소를 가리키는 구조 탓에 GROUP BY와 집계 같은 쿼리 계획이 제약을 받음
- 벡터 하나를 갱신할 때 그 문서를 가리키는 수백 개의 속성과 인덱스를 다시 써야 하는 쓰기 증폭 때문에 인덱싱 처리량 튜닝이 한계에 부딪혔고, v3는 인덱스가 행의 위치를 가리키지 않게 바꾸는 것임
- v3는 텍스트, 정규식, 벡터 검색을 모두 빠르게 하는 동시에 더 많은 SQL 쿼리를 turbopuffer로 옮기는 토대가 되는 것을 목표로 함
Hacker News opinions
처음엔 페이지가 안 열렸다가 지금은 잘 열림. 트래픽 몰려서 그런 거면 미리 부하 테스트를 했어야지.
엔터프라이즈 검색에 순수 벡터 DB 쓸 이유가 거의 없음. 벡터 지원 있는 SQL DB 위에 검색 엔진을 올렸는데, 벡터 유사도는 전문 검색, 필터, 조인, 정렬과 나란한 쿼리 프리미티브 하나일 뿐임. ACL이나 버전, 시간 필터가 평범한 predicate가 되고, 별도 벡터 DB를 두면 갱신할 때마다 두 시스템 동기화하는 게 제일 어려움.
10년 전 Postgres vs InnoDB 논쟁이 검색에서 반복되는 것 같음. InnoDB는 보조 인덱스가 PK를 가리키게 하고 읽기에서 한 번 더 조회하는 비용을 먹었는데, 그 추가 조회가 B-tree 대신 S3 GET이면 얼마나 나올지 궁금함. 클러스터가 벡터 사본을 들고 있어서 검색은 로컬로 하고 결과 가져올 때만 간접 참조 비용을 내는 구조인지도 궁금함.
행이 있는 위치를 가리키지 않으면 인덱스는 대신 뭘 가리키게 되는 거임?
Postgres는 인덱스가 업데이트마다 바뀌는 row-id를 가리키고, MySQL은 프라이머리 인덱스 엔트리를 가리켜서 간접 참조가 하나 더 생기는 대신 안정적인 ID를 가리킴. 그래서 프라이머리 키를 안 건드리면 다른 인덱스를 다시 안 써도 됨.
MySQL이 인덱스 많을 때 유리한 건 맞지만 그게 좋은 스키마 설계에서 Postgres 아키텍처가 더 낫다는 뜻은 아님. 보조 인덱스가 프라이머리 키를 가리키면 undo 로깅이 가능해져서 vacuum이 필요 없어지는데, vacuum이 Postgres에서 제일 아픈 부분임. 프라이머리 키 인덱스는 대부분 캐시에 있어서 간접 참조 비용도 생각보다 작음.
MSSQL의 클러스터드 인덱스나 Oracle의 IOT처럼 선택하게 해주는 게 맞음. 접근 대부분이 프라이머리 인덱스로 가는 상황이면 간접 참조를 피하는 게 성능에 낫고 공간도 아낌. PG에 진짜 클러스터드 인덱스가 없는 게 아쉬움.
속성을 벡터마다 복사하는 건 이해 감. 금방 터지지. 근데 새 프라이머리 인덱스는 뭘로 잡은 거임?
자동 생성되는 내부 ID인 (segment ID, doc ID)임. 사용자가 주는 id 필드는 저장 계층에서 보조 인덱스로 내려감.
벡터 DB는 사실 벡터나 저장보다 검색에 가까운 물건이었는데 용어가 너무 잘 붙어버려서 회사들이 너무 오래 붙들고 있었음.
그럼 그냥 검색 엔진인데, 벡터 지원이 이미 들어간 Elasticsearch나 Vespa랑 가격, 성능, 기능으로 붙어야 함. 누가 페이지에 AI를 더 많이 쓰는지도 경쟁이고.
우리도 그 문제를 일찍 깨닫고 서버리스 검색 엔진을 처음부터 만들었음. dense/sparse 벡터, late interaction, 어휘 검색, 인덱스 정규식, 필터링, 커스텀 스코어링을 한 쿼리에서 지원함.
LanceDB를 비슷한 용도로 잘 쓰고 있음. Lance도 ANN을 보조 인덱스로 다루고 행은 fragment에 있어서 벡터 인덱스가 행을 옮기지 않음.
RAG는 잘 모르는데, DB 자체를 신경망으로 만들어버리려는 시도는 없었나? 전통 DB를 다 걷어내고 오토인코더 같은 걸 쓰는 식으로.
generative retrieval이라는 이름으로 3~4년 전부터 연구가 있음. 트랜스포머 가중치를 인덱스로 쓰고, 쿼리를 넣으면 constrained decoding으로 문서 ID를 생성하는 방식임.
Postgres를 버리고 쓰임새마다 맞춤 DB를 만들자는 얘기면 아직 그럴 때가 아님. 다만 데이터 손실 위험이 없는 검색 인덱스에서는 이미 두 회사가 그렇게 하는 걸 봤고 나도 하고 있음.