본문으로 건너뛰기
최종 수정: 에

관련도 점수 산정

전문 검색 쿼리(예: MATCH_ANY, MATCH_ALL, MATCH_PHRASE 등)를 실행할 때는 관련성이 가장 높은 레코드가 먼저 반환되도록 결과를 "일치도"에 따라 정렬해야 하는 경우가 많습니다. Doris는 관련도 점수 산정 기능을 제공합니다. 쿼리 조건에 따라 각 행에 수치 점수를 부여하며, 점수가 높을수록 관련성이 높다는 의미입니다.

Doris는 현재 관련도 점수 산정의 기본 구현으로 BM25 (Best Matching 25) 알고리즘을 사용합니다.

주요 활용 사례:

  • 검색 엔진 애플리케이션: 키워드를 기준으로 관련성이 가장 높은 문서 목록 반환
  • 로그 분석: 관련도순으로 정렬하여 키워드와 가장 잘 일치하는 로그를 빠르게 탐색
  • 콘텐츠 추천: 텍스트 유사도를 기준으로 우선적으로 제공할 콘텐츠 선별
  • 지식 베이스 검색: 질문과의 관련도순으로 정렬된 답변 후보 반환

빠른 시작​

다음 예제는 쿼리에서 관련도 점수 산정을 활성화하고 점수순으로 정렬하는 방법을 보여 줍니다.

SELECT *,
score() AS relevance
FROM search_demo
WHERE content MATCH_ANY 'text search test'
ORDER BY relevance DESC
LIMIT 10;

쿼리를 실행하면 Doris는 BM25 알고리즘으로 각 행의 점수를 계산하고 관련성이 가장 높은 상위 10개 레코드를 반환합니다.

+------+-----------------------------------+---------+--------------+-----------+
| id | content | author | publish_date | relevance |
+------+-----------------------------------+---------+--------------+-----------+
| 1 | Full text search engine test demo | Alice | 2024-01-01 | 2.915228 |
| 7 | Text processing techniques | Grace | 2024-01-07 | 1.341931 |
| 5 | Performance test framework | Eve | 2024-01-05 | 1.341931 |
| 3 | Advanced search algorithms | Charlie | 2024-01-03 | 1.341931 |
+------+-----------------------------------+---------+--------------+-----------+

활성화 조건​

점수 계산이 적용되려면 쿼리가 다음 세 가지 조건을 모두 충족해야 합니다.

  1. SELECT 절에서 score() 함수를 명시적으로 호출해야 합니다.
  2. WHERE 절에 하나 이상의 MATCH_* 조건이 포함되어야 합니다.
  3. 쿼리가 Top-N 쿼리여야 하며, ORDER BY가 score() 결과를 기준으로 해야 합니다.

지원되는 인덱스 유형​

인덱스 유형점수 산정 지원설명
토큰화된 역색인예BM25 관련도 점수를 계산할 수 있음
토큰화되지 않은 역색인아니요정확히 일치하는 검색만 지원하며 점수는 계산하지 않음

지원되는 쿼리 유형​

  • MATCH_ANY
  • MATCH_ALL
  • MATCH_PHRASE
  • MATCH_PHRASE_PREFIX
  • SEARCH

BM25 알고리즘​

BM25는 확률 모델에 기반한 텍스트 관련도 알고리즘입니다. 단어 빈도(TF), 역문서 빈도(IDF), 레코드 길이라는 세 가지 요소를 함께 고려하여 일치 결과에 가중치를 적용해 점수를 계산합니다. 기존 TF-IDF 모델에 비해 BM25는 더 안정적이고 유연하게 조정할 수 있으며, 긴 텍스트와 짧은 텍스트 간의 점수 차이를 효과적으로 조절합니다.

핵심 수식​

score = IDF × (tf × (k1 + 1)) / (tf + k1 × (1 - b + b × |d| / avgdl))

수식에 사용된 변수의 정의는 다음과 같습니다.

변수의미
tf현재 행에서 쿼리 단어가 등장하는 횟수
IDF단어가 얼마나 드문지를 나타내는 역문서 빈도
|d|현재 행의 길이(토큰화 후 토큰 수)
avgdl테이블에 있는 모든 행의 평균 길이
k1, b알고리즘 조정 매개변수

매개변수​

매개변수기본값설명
k11.2단어 빈도가 점수에 미치는 영향의 크기 조절
b0.75레코드 길이 정규화의 강도 조절
boost1.0쿼리 수준의 가중치 계수

보조 통계​

IDF   = log(1 + (N - n + 0.5) / (n + 0.5))
avgdl = total_terms / total_rows

각 변수의 의미는 다음과 같습니다.

  • N: 테이블의 전체 행 수
  • n: 쿼리 단어를 포함하는 행 수

쿼리에 여러 단어가 포함된 경우, 최종 점수는 각 단어의 점수를 합한 값입니다.

레코드 길이와 norms 속성​

norms 인덱스 속성과 inverted_index_skip_norms_for_variant BE 설정은 Doris 4.1.5부터 지원됩니다.

|d|는 norms에서 가져옵니다. norms는 인덱싱된 필드마다 행당 한 바이트의 공간을 사용하며, 해당 필드에 값이 없는 행도 포함됩니다. 토큰화된 인덱스는 기본적으로 norms를 기록하지만("norms" = "true"), 토큰화되지 않은 인덱스는 기록하지 않습니다. 필터링에만 사용하는 인덱스는 "norms" = "false"로 설정하여 공간을 절약할 수 있습니다.

INDEX idx_content(content) USING INVERTED PROPERTIES("parser" = "english", "norms" = "false")

VARIANT 하위 경로는 인덱스의 norms 속성을 상속하며, rows × paths 바이트의 공간을 사용합니다. BE 설정 inverted_index_skip_norms_for_variant(기본값 false, 런타임에 변경 가능)을 true로 설정하면 모든 VARIANT 경로 인덱스에서 norms가 비활성화됩니다. 이 설정은 인덱스 속성보다 우선합니다.

norms를 비활성화해도 MATCH_* 필터링에는 영향이 없지만, score()가 norms가 없는 세그먼트를 하나라도 읽으면 오류를 반환합니다. 이 설정은 새로 기록되는 세그먼트에 적용됩니다. 기존 세그먼트는 compaction으로 다시 기록될 때까지 그대로 유지됩니다. 이 설정을 변경하기 전에 모든 BE를 해당 설정을 지원하는 버전으로 업그레이드하세요.

결과 해석​

점수 산정 결과를 이해하면 관련도 순위를 더 정확하게 활용할 수 있습니다.

특성설명
점수 범위상한이 정해져 있지 않은 양수이며, 일반적으로 절댓값보다 상대적인 크기가 중요함
여러 단어를 포함한 쿼리여러 단어가 포함되면 전체 점수는 각 단어의 점수를 합한 값임
길이의 영향일치하는 단어가 같을 때는 짧은 레코드가 조금 더 높은 점수를 받음
일치하는 단어가 없는 경우쿼리 단어가 테이블에 없으면 해당 점수는 0임

자주 묻는 질문​

Q1: 쿼리에서 점수가 반환되지 않는 이유는 무엇인가요?

다음 사항을 순서대로 확인하세요.

  1. score() 함수가 SELECT에서 호출되는지 확인합니다.
  2. WHERE 절에 MATCH_* 조건이 포함되어 있는지 확인합니다.
  3. ORDER BY가 score()를 기준으로 하는지 확인합니다.
  4. 인덱스가 토큰화된 역색인인지 확인합니다.

Q2: BM25와 TF-IDF의 차이점은 무엇인가요?

BM25는 TF-IDF를 기반으로 단어 빈도 포화와 길이 정규화라는 두 가지 개선 사항을 도입했습니다. 이를 통해 긴 텍스트와 짧은 텍스트의 점수가 더 균형을 이루고 안정성이 높아집니다.

Q3: 서로 다른 쿼리의 점수를 비교할 수 있나요?

권장하지 않습니다. BM25 점수는 쿼리에 사용된 단어와 테이블의 데이터 분포에 따라 달라집니다. 서로 다른 쿼리 간에는 절댓값을 비교할 수 없습니다. 동일한 쿼리의 결과 집합 내에서만 상대적인 크기를 비교하세요.