Engineering

FAISS에서 SQ8까지

벡터 검색 엔진의 기본 저장 포맷을 찾기까지. FAISS를 기준선으로 두고 F32, SQ8, SQ4, SQ1, TQ4를 비교한 개발 기록.

벡터 검색 성능 이야기를 할 때 FAISS는 여전히 가장 먼저 떠오르는 기준선입니다. 우리도 출발점은 같았습니다. 다만 목표는 FAISS를 그대로 복제하는 것이 아니라, 우리 엔진 안에서 실제로 더 좋은 기본값이 무엇인지 찾는 것이었습니다.

질문은 이것이었습니다.

검색 엔진을 직접 운영한다면, 어떤 저장 포맷이 지연시간, 메모리 사용량, 검색 품질 사이에서 가장 좋은 균형을 만들어낼까?

이번 벤치마크 라운드 끝에 얻은 답은 SQ8이었습니다.

이 글은 그 결론에 도달하기까지의 과정을 정리한 개발 기록입니다.

무엇을 해결하려고 했나

우리가 원한 것은 세 가지였습니다.

  • FAISS와 비슷한 급의 지연시간
  • F32보다 훨씬 낮은 메모리 사용량
  • 기본값으로 써도 될 만큼 안정적인 검색 품질

문제는 이 세 가지가 서로 다른 방향으로 당긴다는 점입니다. 압축을 세게 걸수록 메모리는 줄지만, 지연시간이나 랭킹 품질은 무너지기 쉬워집니다.

그래서 처음부터 “가장 많이 압축되는 포맷”을 찾기보다, “운영 기본값으로 가장 잘 버티는 포맷”을 찾는 방식으로 접근했습니다.

비교한 후보들

이번에 비교한 저장 포맷은 다음과 같습니다.

  • F32: 압축 없는 기준선
  • SQ8: 8비트 scalar quantization, F32 대비 4배 압축
  • SQ4: 4비트 scalar quantization, F32 대비 8배 압축
  • SQ1: 1비트 sign quantization, F32 대비 32배 압축
  • TQ4: TurboQuant 아이디어를 참고한 실험 경로

여기서 중요한 점은 F32를 끝까지 같이 가져갔다는 것입니다. 그래야 압축 포맷끼리 상대 비교만 하는 것이 아니라, 실제 품질 손실과 실제 지연시간 이득을 함께 볼 수 있습니다.

1단계: FAISS를 구현 목표가 아니라 기준선으로 두기

이번 라운드에서 사용한 FAISS HNSW 기준 수치는 다음과 같았습니다.

Enginep50(us)p95(us)p99(us)QPSMB
FAISS HNSW621941165315034096.0

이 기준선이 주는 의미는 단순합니다.

  • 어떤 포맷이 FAISS보다 훨씬 느리면 기본값 후보로 보기 어렵다
  • 조금 느리더라도 훨씬 작으면 여지는 있다
  • 더 빠르고 더 작으면 강력한 후보가 된다

즉, FAISS는 따라가야 할 구현이 아니라 넘어서거나 최소한 버텨야 할 성능 기준이었습니다.

2단계: 200K에서 먼저 후보를 걸러내기

모든 포맷을 바로 1M까지 밀어붙이는 대신, 먼저 200K에서 걸러냈습니다.

조건은 다음과 같았습니다.

  • dim = 1024
  • top_k = 10
  • 쿼리 1000
  • flush -> compact -> preload -> search

결과는 이랬습니다.

FormatBuildp50(us)p95(us)p99(us)QPSMB
F32+HNSW142s5456978801772819.2
SQ8+HNSW165s2213495544207204.8
SQ4+HNSW148s6607979801479102.4
SQ1+HamHNSW358s12901777216173225.6

이 표에서 바로 보이는 사실이 몇 가지 있었습니다.

먼저 SQ1은 후보군에서 사실상 빠졌습니다. 압축률은 인상적이지만, 기본값으로 쓰기에는 지연시간 비용이 너무 컸습니다.

SQ4는 여기서는 꽤 흥미로웠습니다. 작고, 완전히 무너지지도 않았기 때문입니다. 그래서 “혹시 1M에서도 sweet spot이 될 수 있을까?”라는 기대를 남겼습니다.

하지만 가장 눈에 띈 것은 SQ8이었습니다.

  • F32보다 훨씬 작고
  • F32보다 훨씬 빠르고
  • 이 시점에서는 품질 경고도 없었습니다

즉, SQ8은 처음으로 “이건 진짜 기본값 후보 같다”는 느낌을 준 포맷이었습니다.

3단계: 속도만 보지 말고 검색 품질 확인하기

압축 포맷이 빠르고 작아 보여도, 검색 품질이 무너지면 기본값으로는 쓸 수 없습니다.

그래서 SQ8에 대해서는 따로 F32와 정면 비교하는 recall 테스트를 넣었습니다.

조건:

  • 1024d
  • 10,000 vectors
  • 50 queries
  • brute-force top-10을 ground truth로 사용

결과:

MetricValue
F32 recall@100.9960
SQ8 recall@100.9800
Recall delta0.0160

이 수치가 결정적이었습니다.

SQ8은 무손실 포맷이 아닙니다. 하지만 기본값을 결정하는 데 필요한 건 완전한 보존이 아니라, 손실이 충분히 작아서 성능과 메모리 이득이 훨씬 크다는 사실입니다.

이번 결과에서는 바로 그 조건을 만족했습니다.

4단계: 1M에서 최종 비교하기

최종적으로 1M 스케일에서 남은 핵심 비교는 SQ8SQ4였습니다.

FormatBuildp50(us)p95(us)p99(us)QPSMB
SQ8+HNSW839s27739250234001024.0
SQ4+HNSW781s860104812211138512.0
FAISS HNSW reference-621941165315034096.0

이 표가 사실상 최종 결론을 만들었습니다.

이 숫자가 뜻하는 것

SQ8은:

  • FAISS 기준보다 메모리를 4배 적게 쓰고
  • 이 측정 환경에서는 FAISS 기준보다 더 낮은 지연시간을 보였고
  • QPS도 더 높았습니다

반면 SQ4는:

  • 메모리를 SQ8보다 절반 더 아끼지만
  • 1M 스케일에서는 지연시간과 처리량을 너무 많이 내줬습니다

여기서 중요한 건 압축률 자체가 아니라 전체 운영 지점입니다.

기본값의 역할은 “가장 많이 압축되는 포맷”이 되는 것이 아니라, 대부분의 실제 워크로드에서 가장 균형 잡힌 성능을 제공하는 것입니다. 1M에서는 그 균형점이 분명히 SQ8 쪽이었습니다.

5단계: 더 강한 압축을 원하면 TurboQuant 계열이 답일까

자연스럽게 다음 질문이 나옵니다.

SQ8은 좋고 SQ4는 아쉽다면, 더 똑똑한 4비트 경로는 가능하지 않을까?

그래서 SQ4를 고치는 대신, 별도의 TQ4 실험 경로를 만들어봤습니다. 방향은 TurboQuant 아이디어를 참고했지만, 어디까지나 첫 실험이었습니다.

결과는 좋지 않았습니다.

Recall:

MetricValue
F32 recall@100.9920
TQ4 recall@100.4900
Recall delta0.5020

200K latency:

FormatBuildp50(us)p95(us)p99(us)QPSMB
SQ8+HNSW138s2112472814645204.8
TQ4+HNSW144s380341154300263104.0

즉, 첫 번째 TurboQuant 계열 실험은 저장 용량 말고는 거의 이점이 없었습니다. 품질도 나빴고, 속도도 너무 느렸습니다.

이 결과가 말해주는 것은 두 가지입니다.

  1. 지금 당장은 SQ8이 훨씬 더 실용적이다
  2. TurboQuant 계열을 다시 하려면 “조금 더 손보는 수준”이 아니라, 논문에 더 가까운 새로운 구현으로 다시 접근해야 한다

최종 선택

결론은 단순합니다.

  • 기존 컬렉션은 그대로 둔다
  • 새 컬렉션은 SQ8을 기본값으로 사용한다
  • 미지원 차원은 F32로 안전하게 fallback 한다
  • 특정 컬렉션을 다른 포맷으로 바꿔야 하면 raw source data 기준으로 재빌드한다

이 방식의 장점은 명확합니다. 성능 이득은 바로 가져가되, 운영 마이그레이션 프로젝트로 키우지 않아도 됩니다.

한 줄 요약

전체 흐름을 한 표로 줄이면 이렇습니다.

단계결론
FAISS baseline넘어야 할 외부 기준선
F32 baseline속도와 recall의 기준점
SQ1기본값으로는 너무 느림
SQ4흥미롭지만 1M에서는 SQ8보다 약함
SQ8가장 좋은 전체 균형
TQ4 first pass아직 경쟁력 없음

그리고 정말 한 문장으로 요약하면 이렇습니다.

SQ8을 고른 이유는 가장 많이 압축되기 때문이 아니라, 압축 포맷 중 처음으로 “기본값처럼 동작”했기 때문입니다.

최종 벤치

이번 라운드에서 하나만 남겨야 한다면 이 표입니다.

Formatp50(us)p95(us)p99(us)QPSMB
SQ8+HNSW27739250234001024.0
SQ4+HNSW860104812211138512.0
FAISS HNSW621941165315034096.0

이 표가 이번 선택을 만들었습니다.

Ready to try Schift?

Switch embedding models without re-embedding. Start free.

Get started free