적용 대상:SQL Server
Azure SQL 데이터베이스
Azure SQL Managed Instance
CONTAINSTABLE과 FREETEXTTABLE 함수는 0부터 1,000까지의 서수 값(순위 값)을 포함하는 이름의 RANK 열을 반환합니다. 이 값들은 선정 기준과 얼마나 잘 맞는지에 따라 행들을 순위 매깁니다. 순위 값은 결과 집합에 포함된 행의 관련성을 나타내는 상대적 순서일 뿐이며 값이 작을수록 관련이 없는 것입니다. 실제 값은 중요하지 않으며, 쿼리가 실행될 때마다 보통 달라집니다.
참고
CONTAINS과 FREETEXT 조건자는 순위 값을 반환하지 않습니다.
검색 조건과 일치하는 항목 수는 종종 많습니다. 쿼리가 너무 많은 매칭을 반환하지 않도록 CONTAINSTABLEFREETEXTTABLE 선택적 top_n_by_rank 매개변수를 사용하세요. 이 방법은 일부 행만 반환합니다.
top_n_by_rank 는 정수 값 n으로, n 개의 최고 순위 매치만 내림차순으로 반환됨을 명시합니다.
top_n_by_rank 다른 매개 변수와 결합된 경우 쿼리는 실제로 모든 조건자와 일치하는 행 수보다 적은 행을 반환할 수 있습니다.
SQL Server 데이터베이스 엔진은 매칭을 순위별로 정렬하고 지정된 행 수까지만 반환합니다. 예를 들어, 보통 1,000,000행 테이블에서 100,000행을 반환하는 쿼리는 상위 100행만 요청하면 더 빠르게 처리됩니다.
검색 결과를 제한하기 위해 RANK를 사용하는 예시
예제A: 상위 3개의 일치하는 항목만 검색
다음 예제에서는 CONTAINSTABLE를 사용하여 상위 3개 일치 항목만 반환합니다.
USE AdventureWorks2025;
GO
SELECT K.RANK,
AddressLine1,
City
FROM Person.Address AS A
INNER JOIN CONTAINSTABLE (Person.Address, AddressLine1, 'ISABOUT ("des*",
Rue WEIGHT(0.5),
Bouchers WEIGHT(0.9))', 3) AS K
ON A.AddressID = K.[KEY];
GO
결과 집합은 다음과 같습니다.
RANK Address City
----------- -------------------------------- ------------------------------
172 9005, rue des Bouchers Paris
172 5, rue des Bouchers Orleans
172 5, rue des Bouchers Metz
예제 B: 상위 5개의 항목 중 일치하는 것 검색
다음 예에서는 CONTAINSTABLE를 사용하여 Description 열에 light 또는 lightweight 단어 근처에 aluminum"이라는 단어가 포함된 상위 5개 제품에 대한 설명을 반환합니다.
USE AdventureWorks2025;
GO
SELECT FT_TBL.ProductDescriptionID,
FT_TBL.Description,
KEY_TBL.RANK
FROM Production.ProductDescription AS FT_TBL
INNER JOIN CONTAINSTABLE (Production.ProductDescription,
Description, '(light NEAR aluminum) OR (lightweight NEAR aluminum)', 5) AS KEY_TBL
ON FT_TBL.ProductDescriptionID = KEY_TBL.[KEY];
GO
검색어 결과 순위가 결정되는 방식
전체 텍스트 검색은 전체 텍스트 쿼리가 반환한 데이터의 관련성을 나타내는 선택적 점수(또는 순위 값)를 생성할 수 있습니다. 이 순위 값은 모든 행에서 계산되며, 주어진 쿼리의 결과 집합을 관련성에 따라 정렬하는 기준으로 사용할 수 있습니다. 순위 값은 결과 집합에서 행의 상대적인 관련성 순서만 나타냅니다. 실제 값은 중요하지 않으며 일반적으로 쿼리가 실행될 때마다 달라집니다. 순위 값은 전체 쿼리에서 아무 의미도 갖지 않습니다.
순위용 통계
인덱스를 만들 때, 시스템은 순위 매기기 위해 통계를 수집합니다. 전체 텍스트 카탈로그를 구축한다고 해서 단일 인덱스 구조를 직접 만들지는 않습니다. 대신 Full-Text 엔진은 데이터를 인덱싱하면서 중간 인덱스를 생성합니다. 그런 다음 전체 텍스트 검색 엔진은 필요에 따라 이러한 인덱스를 큰 인덱스로 병합합니다. 이 과정은 여러 번 반복될 수 있습니다. 그런 다음 전체 텍스트 엔진은 모든 중간 인덱스를 하나의 큰 마스터 인덱스로 결합하는 "마스터 병합"을 수행합니다.
통계는 각 중간 인덱스 수준에서 수집됩니다. 인덱스를 병합할 때 통계도 병합됩니다. 일부 통계 값은 마스터 병합 프로세스 중에만 생성할 수 있습니다.
데이터베이스 엔진은 쿼리 결과 집합을 순위 매기지만, 가장 큰 중간 인덱스의 통계를 사용합니다. 이 용법은 중간 인덱스가 병합되는지 여부에 따라 달라집니다. 따라서 중간 인덱스가 병합되지 않은 경우 순위 통계의 정확도가 달라질 수 있습니다. 이러한 정확도 차이 때문에 동일한 쿼리가 전체 텍스트 색인 데이터가 추가, 수정, 삭제되고, 작은 색인들이 병합될 때 시간이 지남에 따라 다른 순위 결과가 나타날 수 있음을 설명합니다.
인덱스 크기와 복잡한 계산을 최소화하기 위해 통계를 반올림하는 경우가 많습니다.
다음 목록에는 순위를 계산하는 데 중요한 몇 가지 일반적으로 사용되는 용어 및 통계 값이 포함되어 있습니다.
| 용어/값 | 설명 |
|---|---|
| 속성 | 전체 텍스트가 인덱싱된 행의 열입니다. |
| Document | 쿼리에서 반환되는 엔터티입니다. 데이터베이스 엔진에서는 이것이 행에 해당합니다. 행에 여러 개의 전체 텍스트 인덱싱된 열이 있을 수 있는 것처럼 문서에는 여러 속성이 있을 수 있습니다. |
| Index | 하나 이상의 문서에 대해 반전된 단일 인덱스입니다. 이는 전적으로 메모리 또는 디스크에 있을 수 있습니다. 많은 쿼리 통계는 일치가 발생한 개별 인덱스와 관련이 있습니다. |
| 전체 텍스트 카탈로그 | 쿼리에 대해 하나의 엔터티로 처리되는 중간 인덱스 컬렉션입니다. 카탈로그는 관리자들이 조직의 단위로 보는 것입니다. |
| 단어, 토큰 또는 항목 | 전체 텍스트 검색 엔진에서 일치하는 단위입니다. 문서에서 나오는 텍스트 스트림은 언어별 단어 분기자에 의해 단어나 토큰으로 토큰화됩니다. |
| 발생 | 단어 분리기에 의해 결정된, 문서 속성에서의 단어 오프셋입니다. 첫 번째 단어는 1번, 다음은 2번 등으로 진행됩니다. 구절 및 근접 쿼리에서 오탐을 피하기 위해 문장 끝과 단락 끝은 더 큰 발생 간격을 만듭니다. |
| TermFrequency | 키 값이 연속으로 나타나는 횟수입니다. |
| 인덱스화된 행 수 | 총 인덱스된 행 수 이 값은 중간 인덱스에서 유지되는 카운트를 기반으로 계산됩니다. 정확도가 달라질 수 있습니다. |
| KeyRowCount | 전체 텍스트 카탈로그에서 지정된 키가 포함된 전체 행 수입니다. |
| MaxOccurrence | 지정된 행 속성에 대해 전체 텍스트 카탈로그에 저장된 최대 발생 횟수입니다. |
| MaxQueryRank | 최대 등급 1000는 Full-Text 엔진이 반환합니다. |
순위 계산 문제
순위 계산 과정에는 여러 요인이 영향을 미칩니다. 다른 언어의 단어 분리기는 텍스트를 다르게 토큰화합니다. 예를 들어, 한 단어 분쇄자는 "dog-house" 문자열을 "dog"와 "house"로 나누지만, 다른 단어 분기자는 이를 "dog-house"로 처리합니다. 일치와 순위는 지정된 언어에 따라 달라지는데, 단어뿐만 아니라 문서 길이도 다르기 때문입니다. 문서 길이 차이는 모든 쿼리의 순위에 영향을 줄 수 있습니다.
IndexRowCount와 같은 통계는 매우 다양할 수 있습니다. 예를 들어, 마스터 인덱스에 20억 행이 있는 카탈로그에서는 새로운 문서가 인메모리 중간 인덱스에 인덱싱되고, 인메모리 인덱스 내 문서 수에 따른 해당 문서의 순위가 마스터 인덱스 문서의 순위와 비교해 왜곡될 수 있습니다. 이 때문에 많은 수의 행이 인덱싱되거나 다시 인덱싱되도록 하는 채우기 작업 후에는 ALTER FULLTEXT CATALOG ... REORGANIZE Transact-SQL 문을 사용하여 인덱스를 마스터 인덱스로 병합합니다. 또한 전체 텍스트 엔진은 중간 인덱스의 수 및 크기와 같은 매개 변수를 기반으로 인덱스를 자동으로 병합합니다.
MaxOccurrence 값은 32개 범위 중 하나로 정규화됩니다. 이 정규화는 예를 들어, 50단어 길이의 문서가 100단어 길이의 문서와 동일하게 취급된다는 것을 의미합니다. 다음 표는 정규화를 보여줍니다. 문서 길이가 둘 다 인접 테이블 값 32와 128 사이의 범위에 있기 때문에 실제로 두 문서는 모두 길이가 128인 것으로 처리됩니다(32 <docLength< = 128).
{ 16, 32, 128, 256, 512, 725, 1024, 1450, 2048, 2896, 4096, 5792, 8192, 11585,
16384, 23170, 28000, 32768, 39554, 46340, 55938, 65536, 92681, 131072, 185363,
262144, 370727, 524288, 741455, 1048576, 2097152, 4194304 };
CONTAINSTABLE의 순위
CONTAINSTABLE 순위는 다음 알고리즘을 사용합니다.
StatisticalWeight = Log2( ( 2 + IndexedRowCount ) / KeyRowCount )
Rank = min( MaxQueryRank, HitCount * 16 * StatisticalWeight / MaxOccurrence )
구문 일치는 개별 키와 마찬가지로 순위가 매겨지지만, KeyRowCount (구문을 포함하는 행 수)는 추정치로 실제 수보다 부정확하거나 더 높을 수 있습니다.
NEAR 순위
CONTAINSTABLE는 NEAR 옵션을 사용하여 서로 근접한 두 개 이상의 검색어에 대한 쿼리를 지원합니다. 반환된 각 행의 순위 값은 여러 매개 변수를 기반으로 합니다. 한 가지 주요 순위 요소는 문서의 길이에 비례한 총 일치 횟수(또는 적중)입니다. 따라서 예를 들어 100 단어 문서와 900 단어 문서에 동일한 일치 항목이 포함된 경우 100 단어 문서의 순위가 더 높습니다.
각 적중 항목의 총 길이는 해당 적중 항목의 첫 번째 검색어와 마지막 검색어 사이의 거리를 기준으로 해당 행의 순위에도 영향을 줍니다. 거리가 작을수록 적중이 행의 순위 값에 더 많이 영향을 줍니다. 전체 텍스트 쿼리에서 최대 거리로 정수를 지정하지 않으면, 논리 용어 차이가 100 이상 되는 히트만 포함하는 문서는 순위가 0이 됩니다.
ISABOUT 순위
CONTAINSTABLE는 ISABOUT 옵션을 사용하여 가중치가 적용된 용어에 대한 쿼리를 지원합니다.
ISABOUT는 기존 정보 검색 용어의 벡터 공간 쿼리입니다. 사용되는 기본 순위 알고리즘은 널리 알려진 수식인 Jaccard입니다. 순위는 다음 알고리즘에 설명된 대로 쿼리의 각 용어에 대해 계산된 다음 결합됩니다.
ContainsRank = same formula used for CONTAINSTABLE ranking of a single term (above).
Weight = the weight specified in the query for each term. Default weight is 1.
WeightedSum = Σ[key=1 to n] ContainsRankKey * WeightKey
Rank = ( MaxQueryRank * WeightedSum ) / ( ( Σ[key=1 to n] ContainsRankKey^2 )
+ ( Σ[key=1 to n] WeightKey^2 ) - ( WeightedSum ) )
FREETEXTTABLE의 순위
FREETEXTTABLE 순위는 OKAPI BM25 순위 수식을 기반으로 합니다.
FREETEXTTABLE 쿼리는 굴절 생성(원래 쿼리 단어의 굴절 형태)을 통해 쿼리에 단어를 추가합니다. 이 단어들은 별도의 단어로 취급되며, 생성된 단어와 특별한 관계가 없습니다. 사전 기능에서 생성된 동의어도 가중치가 같은 별도의 단어로 처리됩니다. 쿼리의 각 단어는 순위에 기여합니다.
Rank = Σ[Terms in Query] w ( ( ( k1 + 1 ) tf ) / ( K + tf ) ) * ( ( k3 + 1 ) qtf / ( k3 + qtf ) ) )
Where:
w is the Robertson-Sparck Jones weight.
In simplified form, w is defined as:
w = log10 ( ( ( r + 0.5 ) * ( N - R + r + 0.5 ) ) / ( ( R - r + 0.5 ) * ( n - r + 0.5 ) )
N is the number of indexed rows for the property being queried.
n is the number of rows containing the word.
K is ( k1 * ( ( 1 - b ) + ( b * dl / avdl ) ) ).
dl is the property length, in word occurrences.
avdl is the average length of the property being queried, in word occurrences.
k1, b, and k3 are the constants 1.2, 0.75, and 8.0, respectively.
tf is the frequency of the word in the queried property in a specific row.
qtf is the frequency of the term in the query.