使用 RANK 限制搜索结果

CONTAINSTABLEFREETEXTTABLE 函数返回一个名为 RANK 的列,其中包含从 0 到 1000 的序号值(排名值)。 这些值用于根据返回的行与选择条件的匹配程度对返回的行进行排名。 排名值仅指示结果集中行相关性的相对顺序,值越低,表示相关性越低。 实际值不重要,每次运行查询时通常不同。

注释

CONTAINS 和 FREETEXT 谓词不返回任何排名值。

与搜索条件匹配的项数通常非常大。 若要防止 CONTAINSTABLE 或 FREETEXTTABLE 查询返回太多匹配项,请使用可选的 top_n_by_rank 参数,该参数仅返回行的子集。 top_n_by_rank 是一个整数值 n,该值指定仅以降序返回 n 个排名 最高的匹配项。 如果 top_n_by_rank 与其他参数组合使用,则查询返回的行数可能会少于实际与所有谓词都匹配的行数。

SQL Server 按排名对匹配项进行排序,仅返回指定行数。 这种选择可能会导致性能显著增加。 例如,一个通常会返回一百万行表中 100,000 行的查询,如果只请求前 100 行,则处理速度会更快。

使用 RANK 限制搜索结果的示例

示例 A:仅搜索前三个匹配项即可查询结果

以下示例使用 CONTAINSTABLE 仅返回前三个匹配项。

USE AdventureWorks2012  
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  
  
(3 row(s) affected)  

示例 B:搜索前十个匹配项

以下示例使用 CONTAINSTABLE 返回前 5 个产品的描述,其中 Description 列包含单词“铝”,靠近“light”或“lightweight”这两个单词。

USE AdventureWorks2012  
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  

搜索查询结果的排名方式

SQL Server 中的全文搜索可以生成可选分数(或排名值),该值指示全文查询返回的数据的相关性。 此排名值在每个行上计算,并可用作排序条件,以便按相关性对给定查询的结果集进行排序。 排名值仅指示结果集中行的相对相关性顺序。 实际值不重要,每次运行查询时通常不同。 排名值在查询中不具有任何意义。

排名统计信息

生成索引时,将收集统计信息以用于排名。 生成全文目录的过程不直接导致单个索引结构。 相反,SQL Server 的 Full-Text 引擎会在为数据编制索引时创建中间索引。 然后,Full-Text 引擎根据需要将这些索引合并到更大的索引中。 此过程可以重复多次。 然后,Full-Text 引擎执行“主合并”,将所有中间索引合并为一个大型主索引。

在每个中间索引级别都会收集统计信息。 合并索引后,统计信息也会被合并。 某些统计值只能在主合并过程中生成。

在对查询结果集进行排名时,SQL Server 使用来自最大中间索引的统计信息。 这取决于中间索引是否已合并。 因此,如果中间索引尚未合并,排名统计信息的准确性可能会有所不同。 这解释了为什么同一查询在一段时间内返回不同的排名结果,因为全文索引数据被添加、修改和删除,以及合并较小的索引。

为了尽量减少索引和计算复杂性的大小,统计信息通常进行舍入。

下面的列表包括计算排名中重要的一些常用术语和统计值。

资产
行中的全文索引列。

文档
在查询中返回的实体。 在 SQL Server 中,这对应于一行。 文档可以具有多个属性,就像一行可以具有多个全文索引列一样。

索引
一个或多个文档的单个倒排索引。 这可能完全位于内存中或磁盘上。 有关查询的许多统计数据与发生匹配的单个索引相关。

全文目录
被视为查询的一个实体的中间索引的集合。 目录是 SQL Server 管理员可见的组织单位。

单词、符号或条目
全文引擎中的匹配单位。 文档中的文本流通过语言特定的分词器被标记化为单词或词元。

次数
由单词分隔符确定的文档属性中的词语偏移量。 第一个单词在出现次数 1,下一个单词在出现次数 2,以此类推。 为了避免短语和邻近查询中的误报,句子结束和段落结尾引入了更大的出现间隔。

TermFrequency
键值在行中出现的次数。

索引行数
索引的行总数。 这是基于中间索引中维护的计数计算的。 此数字的准确性可能有所不同。

关键行计数
包含给定键的全文目录中的行总数。

最大出现次数
在全文目录中按行存储给定属性的最大出现次数。

MaxQueryRank
由 Full-Text 引擎返回的最大排名为 1000。

排名计算问题

计算排名的过程取决于多种因素。 不同的语言断字符以不同的方式标记文本。 例如,字符串“dog-house”可以按一个断字符分解为“dog”“house”,并被另一个字符串分解为“dog-house”。 这意味着匹配和排名因指定的语言而异,因为不仅单词不同,而且文档长度也是如此。 文档长度差异可能会影响所有查询的排名。

统计信息(如 IndexRowCount 可能差异很大)。 例如,如果主索引中的目录有 20 亿行,则一个新文档将索引到内存中中间索引中,并且根据内存中索引中的文档数对文档的排名可能会与主索引中的文档的排名倾斜。 因此,建议在任何导致大量行编制索引或重新编制索引的填充操作之后,使用 ALTER FULLTEXT CATALOG ... REORGANIZE Transact-SQL 语句将索引用合并到主索引中。 Full-Text 引擎还将根据中间索引的数量和大小等参数自动合并索引。

MaxOccurrence 值规范化为 32 个范围中的 1。 例如,这意味着,文档 50 字长被视为与文档 100 字长相同的文档。 下面是用于规范化的表。 由于文档长度在相邻表值 32 和 128 之间的范围内,因此它们实际上被视为具有相同的长度 128(32 = 128 <docLength<)。

{ 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.   

另请参阅

使用全文搜索查询