Blog
databrickslakebasepostgresqlvector-searchhybrid-searchragsizing

Lakebase Search 사이징 — 실제 앱과 400만 패시지에서 배운 것

Databricks가 사내 앱 Slide Hub와 MIRACL 400만 패시지로 Lakebase Search(Postgres 확장 기반 벡터·BM25 하이브리드 검색)를 벤치마크한 결과를 정리합니다. 캐시 비율이 적중률과 지연 시간을 결정하는 구조, 후보 수 200 대 1,000의 트레이드오프, CU별 처리량, 재현율과 프로브 수, 월 0.5 CU 상시 운영 비용까지 사이징 판단에 필요한 수치를 실무 관점으로 해석합니다.

Data Dynamics2026년 10월 21일41 min read

검색 기능을 앱에 붙일 때 가장 먼저 부딪히는 결정은 "검색 시스템을 따로 둘 것인가"입니다. 벡터 DB나 검색 엔진을 별도로 운영하면 데이터를 복제해야 하고, 두 시스템 사이의 정합성과 권한 모델을 따로 맞춰야 합니다. Databricks는 2026년 10월 15일 블로그 Sizing Lakebase Search: lessons from a real app and 4 million passages에서 이 질문에 **"앱 DB 안에서 검색을 돌리면 어떻게 되는가"**를 숫자로 답했습니다.

이 글은 그 원문을 정리하고, 사이징 판단에 바로 쓸 수 있도록 수치를 재배열한 것입니다. 원문의 실험 대상은 두 가지입니다.

  • Slide Hub: Databricks 필드 엔지니어가 약 700개 사내 발표 자료에서 슬라이드를 찾아 재사용하는 내부 앱. 슬라이드 행 2만 3천 개, 실제 사용자, 실제 트래픽이 있는 운영 중인 앱입니다.
  • MIRACL English: Wikipedia에서 만든 공개 패시지 코퍼스. 100만·200만·400만 패시지 부분집합으로 규모가 커질 때의 동작을 측정했습니다.

본문의 차트는 원문이 보고한 수치만으로 다시 그린 것입니다. 원문 차트의 전체 곡선이 아니라 본문에 숫자로 명시된 점만 표시했으므로, 점 사이 구간은 보간이 아닌 연결선으로 읽어야 합니다.

원문은 Databricks 플랫폼 위에서 앱을 만드는 개발자·아키텍트를 대상으로 하지만, 결론의 상당 부분은 PostgreSQL에 벡터 인덱스를 얹어 운영하는 모든 팀에 적용됩니다. 마지막 절에서 그 부분을 따로 짚습니다.

1. 앱과 검색을 한 데이터베이스에

Lakebase Search는 2026년 9월에 정식 출시(GA)된 Postgres 확장(extension) 묶음입니다. 별도 검색 서비스가 아니라 앱 테이블 옆에서 실행되므로, 데이터를 검색 시스템으로 복사하지 않고 두 번째 트랜잭션 경로를 유지할 필요도 없습니다.

CREATE EXTENSION lakebase_vector;   -- 임베딩 저장 + lakebase_ann 인덱스 (ANN 검색)
CREATE EXTENSION lakebase_text;     -- lakebase_bm25 인덱스 (BM25 키워드 검색)
-- lakebase_tokenizer 는 선택

구성 요소는 세 가지입니다.

확장역할내부 구조
lakebase_vector임베딩(텍스트 의미를 숫자 벡터로 표현) 저장, lakebase_ann 인덱스로 근사 최근접 이웃(ANN) 검색IVF 파티셔닝(유사한 벡터를 묶어 쿼리가 일부 그룹만 읽음) + RaBitQ 양자화(벡터를 차원당 약 1비트로 압축)
lakebase_textlakebase_bm25 인덱스로 BM25 키워드 검색. <@> 연산자로 점수 계산쿼리 단어 포함 여부로 텍스트 순위를 매기는 표준 방식
lakebase_tokenizer선택. 토크나이저—

Slide Hub의 슬라이드 2만 3천 행은 투표·검색 텔레메트리·변경 이력·미리보기, 그리고 두 인덱스와 같은 서버리스 Lakebase Postgres 인스턴스에 있습니다. 앱은 하나의 연결, 하나의 권한 모델 안에서 데이터와 인덱스를 함께 읽습니다.

Loading diagram…

2. 검색 쿼리: 하이브리드 + RRF

Slide Hub는 하이브리드 검색을 씁니다. 쿼리와 의미가 비슷한 슬라이드를 찾는 벡터 검색과, 쿼리 단어를 포함한 슬라이드를 찾는 BM25 키워드 검색을 결합합니다. 각 방식이 상위 후보(candidate) 목록을 내놓고, SQL 한 문장이 순위 정책 전체를 담당합니다. 두 후보 목록의 순위를 매기고, 통합하고, 앱 필터를 적용하고, 투표 테이블을 조인합니다. 검색과 앱 로직이 하나의 연결·하나의 권한 집합·하나의 커밋을 공유하는 셈입니다.

순위 정책의 세부는 다음과 같습니다.

요소값의미
후보 수방식당 200벡터 200 + BM25 200 (원래 1,000이었음, 4절 참고)
순위 통합RRF, k=60각 목록에서 1 / (60 + 순위) 점수를 받고 두 점수를 더함
유사도 게이트0.70쿼리와 너무 먼 벡터 매치는 버림 (임베딩 모델에 맞춘 임계값)
제목 가중티어별 가산쿼리가 슬라이드 제목에 매치되면 가중치 부여
노트 가중0.5발표자 노트 매치는 절반 가중
범위 필터권한 기반사용자가 볼 수 있는 자산만 반환

RRF 순위 통합(Reciprocal Rank Fusion)은 두 방식의 점수 스케일이 달라도 순위만으로 합칠 수 있어 하이브리드 검색에서 널리 쓰입니다. k=60은 상위 순위 간 점수 차이를 완만하게 만드는 관례적인 값입니다.

3. 부하에서 병목은 어디인가

검색 요청 하나는 두 개의 서로 다른 컴퓨트를 거치며, 어느 쪽이든 한계가 될 수 있습니다.

Lakebase Postgres 컴퓨트

크기 단위는 CU(Compute Unit) 입니다. 1 CU는 약 2 GB RAM과 그에 비례한 CPU·로컬 SSD를 할당합니다.

  • 오토스케일 범위: 최소 0.5 CU ~ 최대 64 CU. 최대값은 최소값보다 16 CU까지만 클 수 있음.
  • 고정 크기: 최대 112 CU. 32 CU 이하 컴퓨트는 0으로 축소(scale-to-zero) 가능.
  • 로컬 파일 캐시(LFC): Postgres는 테이블·인덱스를 8 KB 페이지로 저장하고, 최근 읽은 페이지를 컴퓨트의 LFC에 유지합니다. 캐시는 CU에 비례해 커지며 컴퓨트 메모리의 최대 75%까지 쓸 수 있습니다. 캐시에 없는 페이지는 스토리지에서 읽어 오므로 더 오래 걸립니다.

Databricks Apps 컴퓨트

앱 웹 서버가 도는 곳입니다. 앱당 크기가 고정되어 MEDIUM은 최대 2 vCPU·6 GB, LARGE는 최대 4 vCPU·12 GB입니다. Python 워커 프로세스 하나가 8개 연결의 풀을 갖기 때문에 워커 2개면 최대 16 연결, 4개면 32 연결입니다.

측정 결과: 동시 사용자 500명

부하 생성기가 사용자 수를 단계적으로 올리며 검색 요청을 보냈고, 한 번에 한쪽(Lakebase CU 또는 앱 크기)만 바꿔 한계를 찾았습니다.

Lakebase앱처리량p50 지연 시간
1 CUMEDIUM, 워커 2196 req/s1.8 s
0.5~1 CULARGE, 워커 4193 req/s1.6 s
2 CUMEDIUM, 워커 2201 req/s1.8 s
4 CUMEDIUM, 워커 2219 req/s1.6 s
8 CUMEDIUM, 워커 2336 req/s1.0 s
16 CUMEDIUM, 워커 2349 req/s1.0 s
16 CULARGE, 워커 4662 req/s 이상343 ms

동시 사용자 500명에서 Lakebase CU와 앱 크기 조합별 처리량 가로 막대 차트. 4 CU까지는 약 200 req/s로 평평하고, 8 CU에서 336, 16 CU에 LARGE 앱을 붙이면 662 이상으로 뛴다

이 표에서 읽어야 할 것은 두 구간입니다.

  • 4 CU까지는 Lakebase가 병목. 1 CU에서 앱을 LARGE로 키우고 워커·연결을 두 배로 늘려도 처리량이 그대로입니다(193 대 196). 1 CU에서 검색 SQL은 평균 146 ms, 캐시 1.5 GB로 스토리지에서 1,490만 페이지를 읽었습니다. 8 CU에서는 캐시 12 GB, 평균 34 ms로 줄고 처리량이 약 50% 올랐습니다.
  • 8 CU부터는 앱이 병목. 같은 MEDIUM 앱에 16 CU를 붙여도 4%만 늘고, DB 연결은 대부분 놀고 있습니다. 반대로 16 CU에 LARGE 앱(워커 4)을 붙이자 662 req/s 이상이 나왔고, 거기서는 부하 생성기가 한계였습니다.

원문의 요지: 한계를 먼저 찾고 나서 확장하라. 8 CU 미만이면 Lakebase CU를 올리고, 8 CU부터는 앱 워커를 늘려라.

두 가지 보조 결과도 중요합니다. 연결 풀은 필수입니다. 사용자 50명 기준으로 풀 없이 45 req/s·p95 2.4 s였던 것이 풀을 쓰자 85 req/s·p95 0.7 s가 됐습니다. 반면 쿼리 임베딩 캐시는 부하에서 측정 가능한 차이를 만들지 못했습니다. 임베딩 호출이 아니라 DB 페이지 읽기가 비용의 대부분이라는 뜻입니다.

4. 후보 수와 콜드 스타트

후보 수(candidate limit)는 쿼리가 건드리는 페이지 수를 정하고, 캐시가 비어 있을 때는 그 페이지 수가 곧 지연 시간입니다. Slide Hub는 처음에 방식당 1,000개 후보로 출시됐고, Databricks 문서의 예제 패턴은 40개를 씁니다. 실험은 후보 수만 바꾸면서 공개 쿼리 20개를 세 가지 상태에서 측정했습니다.

  • Cold: 컴퓨트가 0으로 축소됐다가 깨어난 직후 첫 쿼리. 캐시가 비어 있음.
  • First-touch: 깨어 있는 컴퓨트에서 해당 쿼리를 처음 실행.
  • Repeat: 같은 쿼리를 다시 실행. 필요한 페이지가 캐시에 있음.
후보 수ColdFirst-touchRepeat읽은 페이지상위 10개 일치율
40127 ms13 ms5.0 ms5,65574.5%
100240 ms16 ms7.9 ms7,35589%
200387 ms24 ms11.7 ms10,40190.5%
1,000740 ms109 ms35.3 ms28,972100% (기준)

후보 수 40·100·200·1,000별 Cold·First-touch·Repeat 지연 시간 묶음 막대 차트. 콜드 지연 시간은 127에서 740 ms로 커지고, 상위 10개 일치율은 74.5%에서 100%로 오른다

200개에서 상위 10개의 90.5%가 유지되고, 보고되는 매치 건수는 1,000개 때의 81%입니다. 사용자가 200번째 결과 너머로 넘기는 일은 드물기 때문에 Slide Hub는 200으로 바꿔 배포했습니다.

앱과 같은 리전의 잡에서 엔드투엔드로 재면, 후보 200 기준 콜드 검색은 2.9 s, 반복 검색은 40 ms입니다. 콜드 2.9 s는 다음과 같이 나뉩니다.

  1. 엔드포인트가 깨어나는 동안 연결이 약 1 s 대기.
  2. 캐시가 채워질 때까지 각 쿼리가 페이지를 스토리지에서 읽음.
  3. 새 연결의 첫 쿼리는 약 75 ms의 플래닝 비용을 추가로 냄.

원문의 요지: 후보 풀을 작게 유지하라. 200개는 상위 10개의 90.5%를 지키면서 1,000개의 약 1/3 페이지만 읽고 콜드 지연 시간을 절반으로 줄인다.

5. 규모: MIRACL 100만 → 400만 패시지

데이터와 인덱스 준비

전체 MIRACL English 코퍼스는 32,893,221개 패시지입니다. 임베딩 모델은 Slide Hub와 같은 1024차원의 오픈 모델 gte-large-en-v1.5를 썼고, A10G GPU 한 장에 자체 호스팅해 초당 379 패시지를 처리했습니다. 전체 코퍼스 임베딩에 2.95 GPU-시간이 들었고, 같은 작업을 모델 서빙 엔드포인트로 하면 $48.87이었습니다. GPU 결과와 엔드포인트 결과의 벡터는 일치했습니다(평균 코사인 1.0000, 최소 0.9978).

부분집합lakebase_ann 인덱스 크기
100만5.8 GB
200만11.5 GB
400만23.0 GB

400만 행은 바이너리 COPY로 8 CU에서 19분 만에 적재됐습니다.

100만·200만·400만 패시지의 벡터 인덱스 크기 5.8·11.5·23.0 GB 막대 차트와, 캐시 비율 1.0에 필요한 CU 약 3.6·7.2·14.4

캐시 비율이라는 사이징 축

Lakebase Postgres는 CU당 약 1.6 GB의 파일 캐시를 갖습니다. 규모가 커질 때 질문은 하나입니다. 인덱스가 캐시보다 크면 어떻게 되는가? 원문은 각 실험 셀을 "코퍼스 크기 × CU 크기"로 두고, 다음 비율을 정의했습니다.

캐시 비율 = 캐시 크기 ÷ 벡터 인덱스 크기
          (1.0 이면 인덱스가 캐시에 딱 들어감)
 
적중률   = 쿼리가 읽은 페이지 중 스토리지에서 오지 않은 비율

쿼리 믹스는 세 가지입니다.

  • Uniform: 매번 새 제목으로 쿼리하고 반복 없음. 캐시 입장에서 최악.
  • Skewed: 2만 개 제목 풀에서 Zipf 분포로 추출. 실제 검색 트래픽의 일반적인 모델.
  • Cold: 깨어난 직후 캐시가 빈 상태의 첫 쿼리들.

Uniform·Skewed 측정 전에는 적중률이 더 변하지 않을 때까지 같은 믹스로 캐시 워밍업을 했고, 그 이후 결과를 warm이라고 부릅니다.

발견 1: 적중률은 캐시 비율을 따른다

캐시 비율적중률 (Skewed)
0.0745%
0.5786%
1.1497%

캐시 비율 0.07·0.57·1.14에서 적중률 45%·86%·97%를 잇는 꺾은선 차트. 비율 1.0에 기준선이 있다

코퍼스 크기는 적중률을 바꾸지 않습니다. 200만과 400만 점들이 하나의 곡선 위에 겹칩니다. Uniform 믹스는 아무것도 재사용하지 않으므로 몇 포인트 낮게 깔립니다.

이것이 곧 사이징 규칙입니다. 인덱스 크기를 재고, 원하는 캐시 비율이 나오는 CU를 고르고, 곡선에서 적중률을 읽으면 됩니다. 비율은 코퍼스 크기와 무관하므로 200만에서 한 테스트가 400만의 동작을 예측합니다.

원문의 요지: 캐시는 행 수가 아니라 벡터 인덱스 크기로 사이징하라. 인덱스만큼의 캐시가 있으면 페이지의 95~98%를 스토리지 없이 서비스한다.

발견 2: 지연 시간은 적중률을 따른다

Warm 벡터 검색 p50은 캐시 비율 0.07에서 187 ms, 2.3에서 4 ms였습니다. 하이브리드 검색은 비율이 1에 가까워질 때까지 800 ms 근처에 머물다가 33 ms로 떨어졌습니다. 하이브리드 쿼리의 키워드 절반이 가장 많은 페이지를 읽기 때문에 캐시가 가득 찰 때 가장 큰 이득을 봅니다.

캐시 상태벡터 검색 지연 시간
캐시가 인덱스의 1/3 미만160~230 ms
인덱스 전체가 캐시에 들어감11~23 ms

발견 3: 미스 한 번에 약 0.3 ms

미스는 LFC에 없는 8 KB 페이지 하나입니다. 벡터 인덱스에서 한 페이지는 임베딩 한두 개를 담습니다. 측정한 모든 쿼리에 걸쳐 미스 페이지당 실행 시간이 벡터 검색은 약 252 µs, 하이브리드는 약 316 µs 늘었습니다. 2,000 페이지를 미스하는 쿼리는 약 0.5 s를 냅니다. 캐시 비율이 지연 시간을 정하는 이유가 바로 이것입니다. 비율이 쿼리당 스토리지 읽기 페이지 수를 정하기 때문입니다.

쿼리당 미스 페이지 수에 따른 추가 실행 시간. 벡터 검색은 페이지당 252 µs, 하이브리드는 316 µs 기울기의 직선이며 2,000 페이지에서 약 0.5 s

원문의 요지: 스토리지에서 오는 페이지 하나가 약 0.3 ms다. 쿼리당 미스 수 × 0.3 ms로 캐시가 아껴 주는 시간을 추정하라.

발견 4: 캐시에서 읽으면 코퍼스가 커져도 지연 시간은 거의 그대로

캐시 비율을 1.0 근처로 고정하고 코퍼스만 키우면, warm 벡터 지연 시간은 100만400만에서 1123 ms, warm 하이브리드는 276 ms 근처로 평평합니다. 스토리지에서 읽는 콜드 쿼리만 코퍼스와 함께 커집니다. 콜드 벡터는 100만에서 44 ms, 400만에서 133 ms였고, 콜드 하이브리드는 400만에서 911 ms에 달했습니다.

원문은 이것을 "인덱스 전체를 메모리에 둘 필요는 없다"는 말의 정직한 형태라고 부릅니다. RaBitQ가 차원당 약 1비트(float32의 1/32)로 저장하고 IVF가 쿼리당 몇 개 파티션만 읽기 때문에 컴퓨트 메모리는 작게 유지됩니다. 인덱스는 스토리지에 있으므로 컴퓨트는 작아도 되고 0으로 축소할 수도 있습니다. 다만 캐시를 미스한 쿼리는 그 값을 치르고, 그 빈도를 캐시 비율이 통제합니다.

발견 5: 처리량은 컴퓨트에 비례한다

처리량 테스트는 앱을 거치지 않고 하이브리드 쿼리를 Lakebase Postgres에 직접 보냈습니다. 1·4·16·64개 연결을 동시에 열고, 각 연결이 응답을 기다렸다가 다음 쿼리를 보내는 방식입니다. 부하 생성기 CPU는 0 근처였으므로 모든 수치는 Lakebase가 정한 것입니다.

CUSkewed 처리량 (400만)64 연결 시 쿼리 1건 중앙값 대기
2 CU약 4 q/s14.5 s
8 CU약 15 q/s5.2 s
16 CU약 65 q/s343 ms

400만 패시지에서 2·8·16 CU의 Skewed 믹스 처리량 4·15·65 q/s 막대 차트. 16 CU의 Uniform 믹스는 30 q/s

Uniform 믹스는 16 CU에서 30 q/s에 머물렀습니다. 페이지를 전혀 재사용하지 않기 때문입니다. 처리량은 컴퓨트 크기와 캐시 비율이 함께 결정합니다. CU를 올리면 CPU와 캐시가 동시에 커지므로 처리량을 두 번 삽니다.

실제 앱의 쿼리는 대부분 반복되거나 군집을 이루므로 정상 상태 용량은 Uniform이 아니라 warm 적중률이 정합니다.

발견 6: 재현율과 프로브 수

lakebase_ann은 근사 인덱스입니다. Recall@10은 모든 벡터를 정확히 비교한 상위 10개 중 인덱스가 돌려주는 비율입니다. 인덱스는 벡터를 IVF 파티션으로 나누고, lakebase_ann.probes가 쿼리당 읽을 파티션 수를 정합니다.

기본 프로브 수에서 재현율(recall@10)은 코퍼스 크기와 거의 무관했습니다. 100만에서 0.74, 200만과 400만에서 0.75입니다. 프로브를 늘리면 지연 시간을 내고 재현율을 삽니다.

인덱스 빌드프로브Recall@10지연 시간
기본109 (기본값)0.743 ms
기본1,0000.9120 ms
기본2,0000.9549 ms
build_mode = 'quality'109 (기본값)0.803 ms
build_mode = 'quality'5000.9113 ms
build_mode = 'quality'2,0000.97약 50 ms

프로브 수에 따른 Recall@10 꺾은선 차트. 기본 빌드는 109·1,000·2,000 프로브에서 0.74·0.91·0.95, quality 빌드는 109·500·2,000 프로브에서 0.80·0.91·0.97

build_mode = 'quality'로 빌드한 인덱스는 모든 프로브 수에서 재현율을 올렸습니다. 비용은 빌드 시간으로, 400만 패시지에 16 CU로 52분이 걸렸습니다. lakebase_ann.epsilon을 테스트에서 허용된 최대값 4까지 올려도 0.3포인트 미만만 늘었습니다. 재현율은 데이터와 임베딩 모델에 따라 다르므로 자기 데이터로 측정하고 앱이 필요로 하는 프로브 수를 고르라는 것이 원문의 권고입니다. Lakebase Search는 단일 인덱스로 10억 벡터 이상을 지원합니다.

원문의 요지: 벡터 인덱스는 build_mode = 'quality'로 빌드하라. 기본 프로브에서 재현율이 0.74에서 0.80으로 올라가고, 500 프로브·13 ms로 0.91에 도달한다(기본 빌드는 1,000 프로브·20 ms가 필요). 더 높은 재현율이 필요할 때만 프로브를 올려라.

6. 비용

Lakebase 비용은 사용량을 따릅니다. 중지(suspend)된 컴퓨트는 컴퓨트 비용이 없고 스토리지만 별도 과금됩니다. Slide Hub의 30일 청구서에서 Lakebase는 약 1% 였습니다. 내부 앱이라 5분 유휴 후 첫 검색이 느려지는 것을 사용자가 받아들일 수 있어, 운영 DB도 아무도 검색하지 않으면 0으로 축소합니다.

규모 평가 자체도 저렴했습니다.

항목비용
전체 코퍼스 임베딩 (자체 호스팅 A10G)2.95 GPU-시간
같은 작업을 모델 서빙 엔드포인트로$48.87
14분 부하 램프 (사용자 1,000명까지, 109,602 요청, 오류 0)총 $0.13 = 앱 $0.11 + Lakebase $0.02 (0.5~1 CU 오토스케일, 0.21 CU-시간)
1 CU-시간 (AWS US East 정가 기준)0.213 DBU ≈ Premium $0.085 / Enterprise $0.11

원문의 요지: 운영 환경에서는 0으로 축소하지 말고 최소 0.5 CU를 두라. 정가 기준 월 약 $31~40이고, 검색이 컴퓨트가 깨어나기를 약 1 s 기다리거나 빈 캐시로 시작하는 일이 없어진다. 개발·테스트 브랜치는 0으로 축소해도 된다.

7. 사이징 체크리스트

원문의 결론을 실무 절차로 다시 쓰면 다음과 같습니다. 원문은 "큰 책장 앞 책상에 앉은 독자"에 비유합니다. 책장은 스토리지, 책상은 캐시입니다. 책상 위 페이지는 빠르고, 책장까지 걸어가면 약 0.3 ms입니다.

  1. 벡터 인덱스 크기를 먼저 잰다. 행 수가 아닙니다. 1024차원 기준 100만 행에 약 5.8 GB였습니다.
  2. 캐시 비율로 CU를 고른다. 캐시 ≈ 1.6 GB × CU. 비율 1.0 이상이면 적중률 9598%, warm 벡터 검색 1020 ms대를 기대할 수 있습니다.
  3. 후보 수를 줄인다. 방식당 200이면 상위 10개의 9개를 지키면서 페이지 읽기가 1/3로 줍니다.
  4. 인덱스는 quality 모드로 빌드하고, 프로브는 재현율 요구에 맞춘다. 기본 프로브에서 0.80, 2,000 프로브에서 0.97입니다.
  5. 연결 풀을 반드시 둔다. 같은 50명 부하에서 처리량 2배, p95 1/3입니다.
  6. Lakebase가 빨라진 뒤에는 앱 워커를 늘린다. 그 시점에 CU를 더 올려도 소용없습니다.
  7. 운영은 0.5 CU 바닥을 유지한다. 월 $31~40으로 콜드 스타트를 없앱니다. 개발·테스트는 0으로 축소합니다.

아래는 이 규칙을 그대로 옮긴 간단한 추정 계산입니다. 원문의 상수(CU당 1.6 GB, 미스당 0.3 ms)를 쓰며, 실제 값은 자기 데이터로 다시 재야 합니다.

CACHE_GB_PER_CU = 1.6      # 원문: Lakebase Postgres 는 CU당 약 1.6 GB 파일 캐시
MISS_MS = 0.3              # 원문: 스토리지 미스 페이지당 약 0.25~0.32 ms
 
def cache_ratio(index_gb: float, cu: float) -> float:
    return CACHE_GB_PER_CU * cu / index_gb
 
def min_cu_for_ratio(index_gb: float, target_ratio: float = 1.0) -> float:
    return index_gb * target_ratio / CACHE_GB_PER_CU
 
def miss_penalty_ms(pages_touched: int, hit_rate: float) -> float:
    return pages_touched * (1 - hit_rate) * MISS_MS
 
# 예: 400만 패시지, 인덱스 23 GB
print(min_cu_for_ratio(23.0))             # 약 14.4 CU → 16 CU 선택
print(cache_ratio(23.0, 8))               # 0.56 → 원문 곡선상 적중률 약 86%
print(miss_penalty_ms(10_401, 0.86))      # 후보 200 쿼리가 미스로 내는 시간, 약 437 ms

8. Databricks의 세 가지 검색

원문은 끝에서 Databricks 안의 검색 옵션 셋을 구분합니다. 데이터 옆에 있는 것을 고르라는 것이 기준입니다.

옵션위치적합한 경우
Lakebase Search앱의 Postgres DB 안검색이 앱 테이블 옆에 있어야 하고, 쓰기가 즉시 검색에 보여야 할 때
AI Search (구 Vector Search)Unity Catalog의 레이크하우스 테이블 위 관리형 서비스Delta·Iceberg 테이블과 인덱스를 동기화하고 임베딩도 대신 생성. RAG·에이전트·추천
Full-text search 인덱스 (Beta)관리형 Delta·Iceberg 테이블의 SQL 쿼리search·isearch 함수가 매치 불가능한 파일을 건너뛰어 로그·키워드 조회를 가속. 행을 필터링하지 검색창용 순위를 매기지는 않음

9. PostgreSQL을 직접 운영하는 팀에게

원문은 Lakebase의 숫자지만, 구조는 일반 PostgreSQL + 벡터 확장과 같습니다. 8 KB 페이지, 캐시에 있으면 빠르고 없으면 디스크를 읽는다는 사실은 pgvector·pgvectorscale 등 어떤 확장을 쓰든 동일합니다. 저희가 온프레미스 PostgreSQL에서 하이브리드 검색을 설계할 때 그대로 가져갈 수 있다고 보는 교훈은 세 가지입니다.

  • 인덱스 크기 대 캐시 크기가 사이징의 축이다. Lakebase의 LFC 자리에 shared_buffers와 OS 페이지 캐시가 들어갑니다. "벡터 수가 얼마냐"가 아니라 "인덱스가 몇 GB고 메모리에 얼마나 들어가느냐"로 서버를 정해야 합니다. 양자화된 인덱스(RaBitQ와 같은 1비트/차원, 또는 pgvector의 halfvec·binary 양자화)는 이 비율을 바꾸는 가장 직접적인 수단입니다.
  • 후보 수와 프로브 수는 품질 지표를 보면서 줄인다. 상위 10개 일치율과 재현율(recall@10)을 자기 쿼리 셋으로 재면 "1,000이 안전하다"는 직감보다 훨씬 작은 값으로 내려올 수 있습니다. 하이브리드 검색에서는 키워드 쪽이 페이지를 가장 많이 읽는다는 점도 같습니다.
  • DB가 빨라지면 다음 병목은 앱이다. 연결 풀 없이 벤치마크한 숫자는 DB 성능이 아니라 연결 오버헤드를 재는 것이고, 연결 풀이 있어도 워커 수가 한계를 정합니다. 원문처럼 한 번에 한쪽만 바꿔 한계를 찾는 절차가 필요합니다.

반대로 그대로 옮기면 안 되는 것도 있습니다. CU당 1.6 GB, 미스당 0.3 ms, 0으로 축소 시 약 1 s의 깨어남 지연은 Lakebase의 서버리스 구조와 스토리지 계층에 묶인 값입니다. 로컬 NVMe의 미스 비용은 훨씬 작을 수 있고, 네트워크 블록 스토리지는 더 클 수 있습니다. 상수는 자기 환경에서 다시 재되, "미스 페이지 수 × 미스 단가"로 지연 시간을 설명하는 모델 자체를 가져가면 됩니다.

용어집

본문에 나온 용어를 한자리에 정리했습니다. 더 넓은 AI 용어는 AI 용어집을 참고하세요.

용어뜻
Lakebase PostgresDatabricks의 서버리스 PostgreSQL. 컴퓨트와 스토리지가 분리되어 있고 컴퓨트는 0으로 축소할 수 있다.
Lakebase SearchLakebase Postgres 안에서 벡터(ANN)·BM25 검색을 제공하는 Postgres 확장 묶음. 2026년 9월 GA.
CU(Compute Unit)Lakebase 컴퓨트 크기 단위. 1 CU ≈ 2 GB RAM과 비례한 CPU·로컬 SSD. 파일 캐시는 CU당 약 1.6 GB.
로컬 파일 캐시(LFC, Local File Cache)컴퓨트가 최근 읽은 8 KB 페이지를 보관하는 캐시. 컴퓨트 메모리의 최대 75%. 여기 없는 페이지는 스토리지에서 읽는다.
캐시 비율(cache ratio)캐시 크기 ÷ 벡터 인덱스 크기. 1.0이면 인덱스가 캐시에 딱 들어간다. 원문이 제안한 사이징 축.
적중률(hit rate)쿼리가 읽은 페이지 중 스토리지가 아니라 캐시에서 온 비율.
미스(miss)캐시에 없어 스토리지에서 읽은 8 KB 페이지 하나. Lakebase에서 약 0.3 ms.
ANN(Approximate Nearest Neighbor, 근사 최근접 이웃)모든 벡터를 비교하지 않고 가까운 벡터를 근사적으로 찾는 검색. 정확 검색 대비 재현율을 일부 희생한다.
IVF(Inverted File) 파티셔닝유사한 벡터를 파티션으로 묶어 쿼리가 일부 파티션만 읽게 하는 ANN 인덱스 구조.
프로브(probes)IVF 인덱스에서 쿼리당 읽을 파티션 수. 많을수록 재현율↑, 지연 시간↑. lakebase_ann.probes.
RaBitQ 양자화벡터를 차원당 약 1비트로 압축하는 양자화. float32 대비 32배 작다.
BM25쿼리 단어의 포함 여부·빈도로 문서 순위를 매기는 표준 키워드 검색 점수. lakebase_bm25 인덱스, <@> 연산자.
하이브리드 검색(hybrid search)벡터(시맨틱) 검색과 키워드 검색을 결합해 하나의 순위를 만드는 방식.
후보(candidate) / 후보 수각 검색 방식이 순위 통합 전에 내놓는 상위 결과와 그 개수. 읽는 페이지 수를 결정한다.
RRF 순위 통합(Reciprocal Rank Fusion)각 목록에서 1/(k + 순위)를 점수로 주고 합산하는 통합 방식. 점수 스케일이 달라도 순위만으로 합칠 수 있다. k=60이 관례.
유사도 게이트(similarity gate)쿼리와의 유사도가 임계값(여기서는 0.70) 미만인 벡터 매치를 버리는 필터.
재현율(recall@10)정확 검색의 상위 10개 중 근사 인덱스가 돌려준 비율. ANN 품질 지표.
상위 10개 일치율(top-10 overlap)기준 설정(후보 1,000) 결과와 상위 10개가 얼마나 같은지의 비율. 후보 수를 줄일 때의 품질 지표.
build_mode = 'quality'lakebase_ann 인덱스 빌드 옵션. 빌드 시간을 더 쓰고 모든 프로브 수에서 재현율을 높인다.
콜드 스타트(cold start)0으로 축소된 컴퓨트가 깨어나는 과정. 연결 대기 약 1 s + 빈 캐시 페이지 읽기 + 첫 쿼리 플래닝 약 75 ms.
Cold / First-touch / Repeat깨어난 직후 첫 쿼리 / 깨어 있는 컴퓨트에서 처음 실행 / 같은 쿼리 재실행. 캐시 상태에 따른 세 측정 조건.
Warm (측정 조건)같은 쿼리 믹스로 캐시 워밍업을 마쳐 적중률이 안정된 뒤의 측정.
Uniform / Skewed 믹스반복 없는 쿼리 / Zipf 분포로 반복되는 쿼리. 캐시 최악 조건과 실제 트래픽 모델.
Zipf 분포소수 항목이 대부분의 빈도를 차지하는 분포. 검색어 빈도의 일반적인 모델.
연결 풀(connection pool)DB 연결을 미리 열어 두고 재사용하는 구조. Slide Hub는 워커당 8 연결.
MIRACL다국어 검색 벤치마크용 공개 코퍼스. English 부분은 Wikipedia 패시지 3,289만 개, Apache-2.0.
gte-large-en-v1.51024차원 오픈 임베딩 모델(Apache-2.0).
DBUDatabricks 과금 단위. 1 CU-시간 = 0.213 DBU.
p50 / p95지연 시간의 50·95 백분위수. p95는 꼬리 지연을 본다.

참고 자료