该产品表中有700K记录。查询:

SELECT TOP 1 ID, Name FROM Product WHERE contains(Name, '"White Dress"') ORDER BY DateMadeNew desc

大约需要1分钟的时间。名称上的DateMadeNew和Freetext索引上有一个非群集索引。

如果我删除顶部1或订单 - 运行时间少于1秒钟。

这是执行计划的链接。http://screencast.com/t/zdczmzg5n

看起来FullTextMatch具有超过400K的执行。为什么会发生这种情况?如何更快地制作?

更新2010年5月3日

看起来基数不在多字freetext搜索上:

Optimizer估计有28K唱片匹配“白色连衣裙”,而实际上只有1个。http://screencast.com/t/njm3zje4njat

如果我用“白色”代替“白色连衣裙”,则估计数字为“ 27、951”,而实际数字为'28,487',这要好得多。

好像优化器似乎仅使用搜索基数的短语中的第一个单词。

有帮助吗?

解决方案

编辑

http://technet.microsoft.com/en-us/library/cc721269.aspx#_toc202506240

最重要的是,为全文查询选择了正确的连接类型。 FullTextMatch STVF的基数估计对于正确的计划非常重要。因此,要检查的第一件事是FullTextMatch基数估计。这是全文搜索字符串的索引中估计的命中率。例如,在图3中的查询中,这应该接近包含“单词”一词的文档数量。在大多数情况下,这应该非常准确,但是如果估算很长一段路,您可能会产生不良计划。单个术语的估计通常非常好,但是估计多个术语(例如短语或询问)更为复杂,因为不可能知道索引中的项中的术语相交将基于索引中的术语频率。如果基数估计是好的,则可能是由查询优化器成本模型引起的不良计划。解决计划问题的唯一方法是使用查询提示来强制某种类型的联接或优化。

因此,它根本无法从其存储的信息中知道2个搜索术语是否可能是非常独立或通常在一起发现的。也许您应该有2个单独的过程,用于单词查询,您让优化者在其上进行操作,一个用于多个单词的过程,您强迫“足够好”计划(sys.dm_fts_index_keywords,如果您不想要一个可能会有所帮助一个尺寸适合所有计划)。

NB:您的单个单词过程可能需要使用重新编译选项来查看本文。

在SQL Server 2008全文搜索中,我们可以根据所使用的搜索词的基数估计来更改生成的计划。如果查询计划是固定的(就像在存储过程中的参数化查询中一样),则不会发生此步骤。因此,即使该计划对于给定的搜索词不理想,编译的计划也始终为此查询。

原始答案

不过,您的新计划看起来仍然很糟糕。看起来只有从全文查询部分返回1行,但在产品表中扫描了所有770159行。

这如何表现?

CREATE TABLE #tempResults
(
ID int primary key,
Name varchar(200),
DateMadeNew datetime
)

INSERT INTO #tempResults
SELECT 
      ID, Name, DateMadeNew 
      FROM Product 
      WHERE contains(Name, '"White Dress"')


SELECT TOP 1
    *
    FROM #tempResults
    ORDER BY DateMadeNew desc

其他提示

我看不到链接的执行计划,网络警察阻止了这一点,所以这只是一个猜测...

如果没有 TOPORDER BY, ,尝试这样做:

SELECT TOP 1
    *
    FROM (SELECT 
              ID, Name, DateMadeNew 
              FROM Product 
              WHERE contains(Name, '"White Dress"')
         ) dt
    ORDER BY DateMadeNew desc

看起来FullTextMatch具有超过400K的执行。为什么会发生这种情况?

由于您的索引与 TOP 1, ,Optimizer认为,最好遍历索引,检查每个记录的条目。

如何更快地制作?

如果更新统计信息没有帮助,请尝试在查询中添加提示:

SELECT  TOP 1 *
FROM    product pt
WHERE   CONTAINS(name, '"test1"')
ORDER BY
        datemadenew DESC
OPTION (HASH JOIN)

这将迫使发动机使用 HASH JOIN 算法以加入您的表格和完整性查询的输出。

FullText查询被认为是远程源,返回由 KEY INDEX 提供的 FULLTEXT INDEX 定义。

更新:

如果你的 ORM 使用参数化查询,您可以创建计划指南。

  • 使用Profiler拦截查询 ORM 发送 逐字
  • 制定正确的计划 SSMS 使用提示并将其保存为 XML
  • 采用 sp_create_plan_guide 带着 OPTION USE PLAN 强迫优化器始终使用此计划。

我之前遇到了同样的问题。

性能取决于您为全文索引选择哪种唯一索引。我的桌子有两个唯一的列 - IDarticle_number.

查询:

select top 50 id, article_number, name, ... 
from ARTICLE 
CONTAINS(*,'"BLACK*" AND "WHITE*"')
ORDER BY ARTICLE_NUMBER

如果全文索引连接到 ID 然后,根据搜索单词的不同。如果全文索引连接到 ARTICLE_NUMBER UNIQUE 索引然后总是很快。

我有更好的解决方案。

I.让我们首先概述提出的解决方案,因为在某些情况下也可以使用:

  1. 选项(哈希连接) - 不好,因为您可能会出现错误 “查询处理器无法制定查询计划,因为此查询中定义的提示。在不指定任何提示的情况下重新提交查询,而无需使用set forceplan。”

  2. 从...中选择top 1 *。

  3. SP_CREATE_PLAN_GUIDE-不好,对于使用Plan_Guide,您必须保存特定SQL语句的计划,这对动态SQL语句不起作用(例如ORM生成)

ii。我的解决方案包含两个部分1.使用用于全文搜索的自连接表2.使用MS SQL Hash Join提示 MSDN加入提示

您的SQL:

SELECT TOP 1 ID, Name FROM Product WHERE contains(Name, '"White Dress"') 
ORDER BY DateMadeNew desc

应重写为:

SELECT TOP 1 p.ID, p.Name FROM Product p INNER HASH JOIN Product fts ON fts.ID = p.ID
WHERE contains(fts.Name, '"White Dress"') 
ORDER BY p.DateMadeNew desc

如果您在使用/没有城堡活动记录的情况下使用NHIBERNATE,我回答了 邮政 如何编写拦截器以修改查询以替换内在的连接,而内在哈希连接

对此有几个想法:

1)您是否更新了产品表上的统计信息?看到那里的操作上的估计数和实际行数将很有用。

2)您正在使用哪种版本的SQL Server?我在SQL Server 2008上也有类似的问题,事实证明,没有安装服务包1。安装SP1和一个freetext查询,该查询需要几分钟(由于实际执行的实际执行,实际执行)降低了一秒钟。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top