C.W.K.
Stream
Lesson 04 of 05 · published

하이브리드: WHERE 필터 + 벡터 ranking

~22 min · pgvector, hybrid, sql

Level 0Scout
0 XP0/41 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

진짜 프로덕션 query 의 모양

'전체 테이블에서 top-10 nearest' 거의 안 원해. '이 tenant, 이 프로젝트들에서, X 이후 update 된, 유저가 read 권한 있는 가장 가까운 top-10' 을 원해. pgvector 는 이걸 한 SQL statement 로 쓰고 구조화 필터링은 Postgres 에 맡기게 해.

인덱스-aware 필터링

HNSW/IVFFlat 인덱스가 approximate nearest neighbor 먼저 반환; WHERE 필터는 candidate set 에 적용. 필터가 매우 selective 면 Postgres 한테 먼저 필터하고 ranking 하라고 — 보통 CTE 나 partial index 로 달성. EXPLAIN ANALYZE 로 측정.

'iterative' 패턴

인덱스가 candidate 10개 반환했는데 필터 통과 3개뿐일 때 있어. 고침은 over-fetch + re-filter: nearest 100개 요청, 조건 필터, survivor 의 top-10. 진짜 데이터로 over-fetch factor 튜닝.

Code

구조화 필터 있는 하이브리드 query·sql
WITH candidates AS (
    SELECT id, source, chunk_index, text, metadata,
           1 - (embedding <=> $1) AS similarity
    FROM   chunks
    WHERE  metadata->>'tenant'    = $2
      AND  metadata->>'doc_type'  = ANY($3::text[])
      AND  updated_at >= now() - interval '90 days'
    ORDER BY embedding <=> $1
    LIMIT 100                       -- 필터 위해 over-fetch
)
SELECT *
FROM   candidates
WHERE  similarity >= 0.30           -- 최소 품질 floor
ORDER  BY similarity DESC
LIMIT  10;
Python 에서 같은 query·python
with conn.cursor() as cur:
    cur.execute(open('hybrid_query.sql').read(), (query_vec, 'cwkpippa', ['markdown', 'code']))
    rows = cur.fetchall()

for row in rows:
    print(f'{row[5]:.3f}  {row[1]}#{row[2]}  → {row[3][:80]}')

External links

Exercise

본인 데이터로 하이브리드 query 작성: vector ranking + 본인 선택 구조화 필터 2개. EXPLAIN ANALYZE 실행. 인덱스 사용 확인. over-fetch 한도 (LIMIT 30, 100, 300) 다양화 + survivor count 안정화 자리 보고.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.