역순위 융합(Reciprocal Rank Fusion)
핵심 요약 Apache Doris는 내장
rrf()함수를 제공하지 않지만, 일반 SQL로 Reciprocal Rank Fusion을 구현할 수 있습니다. 이 패턴은ROW_NUMBER()를 BM25 순위와 벡터 순위에 적용한 다음, 두 목록에서1.0 / (60 + rank)를 합산하며 표준 평활화 상수로k = 60을 사용합니다. 그 결과 BM25 점수와 코사인 거리 사이의 보정 없이도 순서가 결정되는 하나의 융합된 top-K 목록을 얻습니다.

Apache Doris에서 Reciprocal Rank Fusion을 사용하는 이유는 무엇인가요?
Reciprocal Rank Fusion은 Apache Doris 하이브리드 검색에서 서로 호환되지 않는 두 점수 척도를 보정하지 않고도 BM25 결과와 벡터 결과를 병합할 수 있는 타당한 기본 방법을 제공합니다. 하이브리드 검색은 동일한 쿼리에 대해 순위가 매겨진 두 목록을 반환합니다. 하나는 전문 검색 결과(score()를 통한 BM25 점수)이고, 다른 하나는 벡터 유사도 결과(l2_distance_approximate 또는 inner_product_approximate)입니다. 두 점수는 서로 호환되지 않는 척도를 사용합니다. BM25 점수는 상한이 없는 양수이며 그 값은 코퍼스 통계에 따라 달라집니다. 코사인 거리는 0과 2 사이에 있고, L2 거리에는 상한이 전혀 없습니다. 이러한 점수를 더하거나 평균을 내도 타당한 의미를 갖는 값이 되지 않으며, 쿼리별 최소-최대 정규화도 취약합니다. 어느 한 목록에라도 이상치가 하나 있으면 융합 결과가 크게 왜곡됩니다.
Reciprocal Rank Fusion은 점수를 버리고 순위만 유지하여 이 문제를 피합니다. 조정할 매개변수가 하나뿐이며, Cormack, Clarke, Buettcher가 2009년에 발표한 이후 검색 벤치마크에서 꾸준히 좋은 성능을 보여 왔습니다.
- BM25 점수와 벡터 거리는 서로 다른 척도를 사용하므로, 이를 산술 연산으로 결합하는 것은 안전하지 않습니다.
- 쿼리 하나에서 긴 꼬리 형태의 점수 분포가 나타나면 최소-최대 정규화가 제대로 작동하지 않습니다.
- 애플리케이션 측 융합 서비스를 두면 배포하고 데이터베이스와 동기화 상태를 유지해야 할 대상이 하나 더 늘어납니다.
Apache Doris의 Reciprocal Rank Fusion이란 무엇인가요?
Apache Doris의 Reciprocal Rank Fusion은 내장 함수가 아니라 SQL 패턴입니다. ROW_NUMBER, FULL OUTER JOIN, 표준 1/(k+rank) 공식을 사용해 표현한 순위 기반 융합 알고리즘입니다. 문서 d가 순위 목록 R_1, R_2, ..., R_n에 나타날 때, 융합 점수는 해당 문서가 나타나는 각 목록에서 순위의 역수를 구해 합산한 값입니다.
score(d) = Σ 1 / (k + rank_i(d))
rank_i(d)는 문서 d가 목록 i에서 차지하는 1부터 시작하는 순위입니다. k는 평활화 상수이며, Cormack 등이 권장하고 대부분의 프로덕션 시스템에서 사용하는 값은 60입니다. 목록에 없는 문서는 해당 목록에서 점수에 기여하지 않습니다. 그런 다음 융합 점수를 내림차순으로 정렬하여 최종 순위를 생성합니다.
Apache Doris에서는 이를 함수가 아닌 SQL 패턴으로 구현합니다. BM25용과 ANN용으로 순위가 매겨진 서브쿼리를 각각 작성하고, 각 행에 ROW_NUMBER()를 부여한 다음, FULL OUTER JOIN으로 결합하고 역수를 합산합니다.
주요 용어
score(): 역색인에 사용하는 Doris의 BM25 점수 함수입니다.MATCH_*조건식, 점수를 기준으로 하는ORDER BY,LIMIT가 있는 단일 테이블 쿼리에서만 작동하며, 변형 없이 그대로 선택해야 합니다(score() AS s). 순위를 매기거나 반올림하는 작업은 외부 쿼리에서 수행합니다.l2_distance_approximate/inner_product_approximate: Doris의 벡터 인덱스(HNSW 또는 IVF)를 기반으로 하는 ANN 거리 함수입니다.ROW_NUMBER() OVER (ORDER BY ...): 결과 집합 내 각 행에 1부터 시작하는 순위를 부여합니다.k: RRF 평활화 상수입니다. 값이 낮으면(20–40) 상위 순위 행의 영향력이 커지고, 값이 높으면(80+) 순위에 따른 영향력 차이가 줄어듭니다.
Apache Doris에서 Reciprocal Rank Fusion은 어떻게 작동하나요?
Apache Doris는 순위가 매겨진 두 검색을 서브쿼리로 실행하고, 각각에 ROW_NUMBER()를 부여한 다음, 문서 id를 기준으로 두 목록을 FULL OUTER JOIN으로 결합하고 1/(k+rank)를 합산하여 최종 순서를 결정하는 방식으로 Reciprocal Rank Fusion을 구현합니다. 아래의 다섯 단계는 검색, 순위 부여, 조인, 융합, 결과 제한 과정을 설명합니다.
- 순위가 매겨진 두 검색을 실행합니다. BM25 서브쿼리는
MATCH_ANY로 필터링하고score()를 기준으로 내림차순 정렬합니다. ANN 서브쿼리는 벡터 거리를 기준으로 오름차순 정렬합니다. 각각LIMIT N으로 결과 수를 제한하며,N은 후보 풀의 크기입니다(일반적으로 50–200). - 각 목록에 순위를 부여합니다.
ROW_NUMBER() OVER (ORDER BY ...)는 각 서브쿼리 내 행에 1, 2, 3 순서로 번호를 매깁니다. 이 번호는 정수이므로 서로 다른 실행 결과 사이에서도 안전하게 결합할 수 있습니다. BM25 목록에서는 윈도우 함수를score()를 계산하는 쿼리보다 한 단계 바깥에 배치합니다.ROW_NUMBER() OVER (ORDER BY score() DESC)를 같은SELECT에서 사용하면score() function requires WHERE clause with MATCH function, ORDER BY and LIMIT for optimization오류로 거부됩니다. - 문서 id를 기준으로 두 목록을 외부 조인합니다.
FULL OUTER JOIN은 어느 한 목록에라도 나타나는 문서를 유지합니다. 한쪽에 없는 행은 해당 순위가NULL이 됩니다. - 역수를 합산합니다.
COALESCE(1.0/(60+bm25_rank), 0) + COALESCE(1.0/(60+ann_rank), 0)으로 각 문서의 융합 점수를 계산합니다. 누락된 순위는 점수에 기여하지 않으며, 이는 원래 RRF 정의와 일치합니다. - 정렬하고 결과 수를 제한합니다.
ORDER BY rrf_score DESC LIMIT K는 최종 top-K를 반환합니다.
후보 풀 크기 N은 중요합니다. 각 검색기에서 상위 10개만 가져오면, BM25에서 11위이고 ANN에서 1위인 문서는 벡터 검색으로만 찾은 결과로 보입니다. 각 검색기에서 후보 100개를 가져오는 것이 합리적인 기본값이며, 재현율이 중요한 워크로드에서는 이 값을 늘리세요.
빠른 시작
벡터 인덱스 및 하이브리드 검색 예제와 동일한 네 개의 행을 사용하며, 댓글 텍스트는 body에 저장합니다.
CREATE TABLE docs (
id INT NOT NULL,
embedding ARRAY<FLOAT> NOT NULL,
body STRING NOT NULL,
INDEX idx_body(body) USING INVERTED PROPERTIES("parser"="english"),
INDEX idx_vec(embedding) USING ANN
PROPERTIES("index_type"="hnsw","metric_type"="l2_distance","dim"="8")
) DUPLICATE KEY(id) DISTRIBUTED BY HASH(id) BUCKETS 1;
INSERT INTO docs VALUES
(1, [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8], 'this is about music'),
(2, [0.2,0.1,0.5,0.3,0.9,0.4,0.7,0.1], 'sports news today'),
(3, [0.9,0.8,0.7,0.6,0.5,0.4,0.3,0.2], 'latest music trend'),
(4, [0.05,0.06,0.07,0.08,0.09,0.1,0.2,0.3], 'politics update');
SELECT COALESCE(b.id, a.id) AS id,
COALESCE(1.0 / (60 + b.r), 0) + COALESCE(1.0 / (60 + a.r), 0) AS rrf
FROM (
-- BM25 list: score() stays plain here; ROW_NUMBER() ranks it one level up
SELECT id, ROW_NUMBER() OVER (ORDER BY s DESC) AS r
FROM (SELECT id, score() AS s FROM docs
WHERE body MATCH_ANY 'music' ORDER BY s DESC LIMIT 100) bm25_hits
) b
FULL OUTER JOIN (
-- ANN list
SELECT id, ROW_NUMBER() OVER (ORDER BY dist ASC) AS r
FROM (SELECT id, l2_distance_approximate(embedding, [0.1,0.1,0.2,0.2,0.3,0.3,0.4,0.4]) AS dist
FROM docs ORDER BY dist ASC LIMIT 100) ann_hits
) a ON b.id = a.id
ORDER BY rrf DESC LIMIT 5;
예상 결과
+------+---------+
| id | rrf |
+------+---------+
| 1 | 0.03224 |
| 3 | 0.03201 |
| 4 | 0.01639 |
| 2 | 0.01587 |
+------+---------+
BM25는 문서 3을 첫 번째로, 1을 두 번째로 배치합니다(이 두 문서에만 "music"이 포함됩니다). 벡터 목록의 순서는 4, 1, 2, 3입니다. 문서 1은 두 목록에서 모두 두 번째이므로 점수가 1/62 + 1/62 ≈ 0.0322가 되어 문서 3보다 근소하게 앞섭니다. 이 문서는 BM25에서는 첫 번째이지만 거리 기준으로는 마지막입니다(1/61 + 1/64 ≈ 0.0320). 문서 4와 2는 벡터 목록에만 나타나며 그 뒤를 잇습니다.
Apache Doris에서 Reciprocal Rank Fusion은 언제 사용해야 하나요?
RAG 파이프라인, 카탈로그/문서 검색, 그리고 절대 점수를 보정하기 어려운 상황에서 BM25 검색과 벡터 검색을 결합하는 모든 워크로드에 Apache Doris Reciprocal Rank Fusion을 사용하세요. 단일 검색기 워크로드, 매우 작은 후보 풀, 보정된 확률이 필요한 사례, 추가 조인으로 지연 시간이 늘어나는 핵심 경로 쿼리에는 사용하지 않는 것이 좋습니다.
적합한 경우
- 키워드와 임베딩 유사도를 모두 사용해 검색하고, LLM에 전달할 하나의 병합된 top-K가 필요한 RAG 파이프라인.
- 키워드 재현율과 의미 기반 재현율이 서로 보완되며, 타당한 기본 순위를 원하는 Catalog 또는 문서 검색.
- 코퍼스나 쿼리 분포가 변하기 때문에 검색기 간 절대 점수를 보정하기 어려운 워크로드.
- 애플리케이션 계층에 별도의 융합 서비스를 구축해야 하는 경우. 융합을 SQL에서 처리하면 데이터 경로를 짧게 유지할 수 있습니다.
적합하지 않은 경우
- 단일 검색기 워크로드. BM25만 실행하거나 ANN만 실행한다면 해당 검색기의 점수로 정렬하고 조인은 생략하세요. 하나의 목록에 RRF를 적용하는 것은 순위를 단조 변환하는 것에 불과합니다.
- 매우 작은 후보 풀(각 검색기에서 상위 5개 또는 상위 10개). RRF는 두 목록에 모두 나타나는 문서에 더 높은 점수를 주는데, 그러려면 두 목록의 길이가 모두 충분해야 합니다. 검색기마다 최소 50개를 가져오세요.
- 보정된 확률이 필요한 워크로드(임계값 적용, 판단 유보, 후속 비용 모델 등). RRF 점수는 확률이 아니며 쿼리 간에 통용되는 절대적인 의미도 없습니다. 보정이 필요하다면 학습 기반 랭커를 사용하세요.
- 추가 서브쿼리와 조인으로 지연 시간이 늘어나는 핵심 경로 쿼리. 사전 필터링 패턴(
MATCH_ANY+ORDER BY l2_distance_approximate)은 한 번의 처리로 순위가 매겨진 단일 목록을 반환하며, 하이브리드 검색에서 기본적으로 사용하는 방식입니다.
k 조정
k를 낮추면(20에 가깝게) 순위 1과 순위 5 사이의 격차가 커지므로, 한 검색기가 확실히 더 신뢰할 만할 때 도움이 됩니다. k를 높이면(100에 가깝게) 곡선이 완만해지고 두 목록 모두에서 하위 순위에 나타나는 문서에 더 높은 점수를 부여합니다. k를 한 번 변경한 뒤, 레이블이 지정된 데이터셋에서 재현율을 측정하고 조정을 마치세요. 쿼리마다 조정해야 한다면 학습 기반 랭커가 필요하다는 신호입니다.
더 읽어보기
- 하이브리드 검색: 역색인 필터링과 ANN 순위를 결합하는 Doris의 기본 단일 처리 패턴으로, 이 카드에서 비교하는 대안입니다.
- 관련도 점수 산정(BM25): 융합에 사용하는 두 입력 중 하나인
score()의 계산 방식과 활성화 조건을 설명합니다. - 역색인 개요: 인덱스 유형, 토크나이저, BM25 서브쿼리를 구동하는
MATCH_*연산자를 설명합니다. - 벡터 인덱스 개요: HNSW 및 IVF 백엔드, 거리 함수, ANN 서브쿼리의 제약 조건을 설명합니다.
- ROW_NUMBER: 순위가 매겨진 각 서브쿼리의 결과를 정수 순위로 변환하는 윈도우 함수입니다.
- Cormack, Clarke, Buettcher (2009): Reciprocal Rank Fusion은 Condorcet 및 개별 순위 학습 방법보다 우수한 성능을 보인다: 원 논문이자
k = 60권장값의 출처입니다.