5

我正在经历管理工作室 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)'
    ) AS KEY_TBL
    ON FT_TBL.ProductDescriptionID = KEY_TBL.[KEY]
 WHERE KEY_TBL.RANK > 2
 ORDER BY KEY_TBL.RANK DESC;

当我使用 Go (在查询之前)和不使用 Go 运行它时,结果是不同的。我又玩了一些 - 复制了选择并添加了 go ,结果仍然不同。从图片中注意,它是相同的选择写入两次但有两个不同的结果

在此处输入图像描述

任何想法?

编辑: 刚刚发现执行计划不同,因为 go
------LINK----------

在此处输入图像描述

4

2 回答 2

6

我可以重现这个

初步测试

假设一个 GO..SELECT..GO 模式和一些空行

Before     After    Rows
y          n        6
y          y        4
n          y        4
n          n        4

如果我改变事件的顺序......

Before     After    Rows
y          n        6
y          y        4
n          n        4
n          y        4

然后再次

Before     After    Rows
y          y        4
n          n        4
n          y        4
y          n        6

Before     After    Rows
y          y        4
n          n        4
y          n        6
n          y        4

@MartinSmith 回答后更新

如果我删除 WHERE,那么无论空行如何,我都会为四个查询获得相同的结果和相同的排名值。使用 WHERE 我得到与上面相同的结果。

马丁表明等级是任意的,但他的同一个链接也指出

这就解释了为什么随着全文索引数据的添加、修改和删除以及较小的索引被合并,同一个查询会随着时间的推移返回不同的排名结果。

在这种情况下,数据是静态的,查询是相同的,除了空行。

更改查询文本

  • With WHERE KEY_TBL.RANK > 0= 相同的行数和排名值
  • 没有 WHERE 子句 = 相同的行数和排名值
  • 将 CONTAINSTABLE 包裹在TOP 200000..ORDER BY RANK= 相同的行数和排名值中,无论 WHERE

与原WHERE KEY_TBL.RANK > 2

  • 每次将第一FT_TBL个别名的大小写更改为不同 ( fT_TBL, Ft_TBL, FT_tBL, FT_TbL),这意味着不同的查询计划 = 相同的行数和排名值
  • 将所有 FT_TBL别名更改为FT_TBl= 相同的行数和排名值
  • 将所有 别名更改FT_TBlFT_TBL=基于空白行的不同排名值 -> 不同的行数

对于最后一个查询(不同的等级值),我得到 4 个相同的执行计划。过滤器在 JOIN 之前应用于 TVF。

  • 在 WHERE 之前的 ON 之后添加一个空行(保持前导和尾随空行)= 相同的行数和排名值
  • 在 FROM = 相同的行数和排名值之前添加一个空行
  • 在 JOIN 之后添加 3 个空格 = 相同的行数和排名值

添加DBCC DROPCLEANBUFFERS

  • 在顶部 4-4-6-4 行添加 DBCC DROPCLEANBUFFERS
  • 如果我在每个查询之前添加 DBCC DROPCLEANBUFFERS
  • 在第一个查询之前或之后添加额外的空行(使用 DBCC)会提供更多行 (6-4-6-4)。错误地发现了这一点,但又回到了第一个观察结果,即空白行会影响结果

在保罗发表评论后

注意尾随和前导空行。

这可靠地失败了。第二个查询给出 4 行

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)'
   ) AS KEY_TBL
   ON FT_TBL.ProductDescriptionID = KEY_TBL.[KEY]
WHERE KEY_TBL.RANK > 2
ORDER BY KEY_TBL.RANK DESC;

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)'
   ) AS KEY_TBL
   ON FT_TBL.ProductDescriptionID = KEY_TBL.[KEY]
WHERE KEY_TBL.RANK > 2
ORDER BY KEY_TBL.RANK DESC;
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)'
   ) AS KEY_TBL
   ON FT_TBL.ProductDescriptionID = KEY_TBL.[KEY]
WHERE KEY_TBL.RANK > 2
ORDER BY KEY_TBL.RANK DESC;
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)'
   ) AS KEY_TBL
   ON FT_TBL.ProductDescriptionID = KEY_TBL.[KEY]
WHERE KEY_TBL.RANK > 2
ORDER BY KEY_TBL.RANK DESC;

GO

每次在我 shift+TAB 整个查询以删除缩进之后,这都会给出相同的结果

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)'
) AS KEY_TBL
ON FT_TBL.ProductDescriptionID = KEY_TBL.[KEY]
WHERE KEY_TBL.RANK > 2
ORDER BY KEY_TBL.RANK DESC;

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)'
) AS KEY_TBL
ON FT_TBL.ProductDescriptionID = KEY_TBL.[KEY]
WHERE KEY_TBL.RANK > 2
ORDER BY KEY_TBL.RANK DESC;
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)'
) AS KEY_TBL
ON FT_TBL.ProductDescriptionID = KEY_TBL.[KEY]
WHERE KEY_TBL.RANK > 2
ORDER BY KEY_TBL.RANK DESC;
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)'
) AS KEY_TBL
ON FT_TBL.ProductDescriptionID = KEY_TBL.[KEY]
WHERE KEY_TBL.RANK > 2
ORDER BY KEY_TBL.RANK DESC;

GO

还在寻找

好的,是时候搜索 MS Connect。新的:https ://connect.microsoft.com/SQLServer/feedback/details/788691/blank-lines-before-and-after-full-text-query-change-results

于 2013-05-27T15:31:26.897 回答
1

我无法在我的机器上重现它,但怀疑这是设计使然,错误正在过滤WHERE KEY_TBL.RANK > 2

主题如何对搜索查询结果进行排名(全文搜索)状态

此排名值在每一行上计算,并可用作排序标准,以按相关性对给定查询的结果集进行排序。排名值仅指示结果集中行的相对相关顺序。实际值并不重要,并且每次运行查询时通常都会有所不同。排名值在查询中没有任何意义。

在第二个查询中,所有值似乎都FLOOR(20% * RANK)从第一个查询按比例缩小。由于这只是对绝对值的相对比例过滤,因此RANK似乎可能会导致匹配行任意进出结果的此类问题。

于 2013-05-27T23:26:46.347 回答