【问题标题】:SQL Server R2 2008 Full Text Search causing 'wait timeouts' randomlySQL Server R2 2008 全文搜索随机导致“等待超时”
【发布时间】:2017-07-04 07:45:41
【问题描述】:

我们有一个部署到生产环境的 ASP MVC 站点,这是一个非常大/很受欢迎的站点,它获得了相当多的流量。

我们正在使用全文搜索来排除搜索功能。

非常随机,我在我们的 ELMAH 日志中看到一堆错误,“等待操作超时”。当这个错误发生时,我们的许多客户似乎都是同时发生的——例如。我们在同一个时间戳中记录了 4 或 5 个此错误的实例。它似乎永远不会孤立地发生。

基本上,在我们的目录页面上,我们会执行 5-6 个查询(例如“获取所有子类别”、“获取所有制造商”、“获取最低/最高价格范围”、“获取实际产品”),我从堆栈跟踪可以看出,这将是导致异常的这些方法之一。

但是,常见的是它们采用用户的过滤器选项并将它们应用于每个查询以显示相关信息。

所以似乎只有在存在搜索词时才会失败(非常罕见)。例如,当客户查看没有搜索词的目录页面时,我没有看到任何其他超时问题。

谁能指出可能发生死锁的方向?我们的全文索引在一个视图上,它从我们的产品表中提取数据。这确实会每天多次更新股票信息等,但视图拉入的列不会频繁更改其数据。 因为它是如此随机,所以很难确定它发生的位置——当我导航到一个我可以看到之前导致异常的 URL 时,页面加载得非常快(好像搜索结果已经在某种程度上被缓存了) .

更多信息: 视图中有 54,612 行(2 列 - 产品 ID/搜索文本) 全文索引的 SearchText 列最大行有 95 个字符,因此它不是海量数据。大多数情况下,目录页面需要大约 600 毫秒来呈现,这些查询通常需要大约 20-30 毫秒。然而,有时这会大量膨胀——我已经看到执行每个查询大约需要 6 秒的跟踪,其他时候 6 个查询中的一个会超时并且只是非常随机的峰值。我自己从未真正经历过这种减速,但我不经常浏览该网站,但我们有新的遗物交易(和错误日志)显示频繁减速和超时。

我们正在使用

进行查询
@Search = '("some*" AND "search*" AND "terms*")'

SELECT TOP ? * FROM (SELECT p.Score, [columns], [Rank] as SearchRank, ROW_NUMBER() OVER 
( ORDER BY p.Score * [Rank] DESC, p.Id DESC) AS row_number 
FROM Product p 
INNER JOIN Manufacturer AS m ON p.ManufacturerId = m.Id 
INNER JOIN ProductCategory pcm ON p.Id = pcm.ProductId 
INNER JOIN CONTAINSTABLE(vw_SearchProducts, FullSearch, @Search) AS FTS ON p.Id = FTS.[KEY] 
WHERE p.Deleted = ? AND pcm.CategoryId = @CategoryId) p WHERE p.row_number > ? ORDER BY p.Score * SearchRank DESC, p.Id DESC 

我们的视图看起来像这样,使用 ProductID 作为 FTS 键:

SELECT p.Id AS ProductId, Colour + ' ' + Size ' ' +  m.Name + ' ' + Categories AS FullSearch 
FROM Product 
INNER JOIN Manufacturer m ON m.Id = p.ManufacturerId
WHERE Deleted = 0 

我们的产品表包含一些用于性能目的的非规范化数据。 我们对目录页面的 6 个主要查询都与上述类似,但只是为符合过滤/搜索条件的产品提取不同的数据位。

我们实际上很快就会升级到 SQL Server 2016 - 不确定这是否会让事情变得更好。

干杯

【问题讨论】:

    标签: sql-server full-text-search


    【解决方案1】:

    您能否启动 SQL Server Profiler 并让它运行几个小时或一天,然后当您再次在日志中看到超时时,找到在该时间前后记录在 SQL Profiler 中的查询并检查 Duration/Reads/Writes 列的值.

    也许通过这种方式,您将能够识别导致超时的具有特定参数列表的 EXACT 存储过程/语句。如果是这样,您将能够使用 SSMS 和执行计划选项卡进一步调试它。

    当然,另一个想法是 FTS 目录可能重建得太频繁了。这也可以被捕获,但您需要捕获确切的超时时间,然后检查 FTS 目录状态是否正在重建。

    当您升级到 SQL 2012-2016 时,FTS 尤其是 FTS 索引更新速度方面的情况应该会有所改善。 MS 声称此类并发 FTS 索引更新的速度高达 x10 倍,请参阅此答案:Are there any Sql Server Full-Text Search (FTS) performance improvements since version 2008 R2?

    55K 的数据记录真的不多。我们针对数百万条记录运行 SQL Server FTS,并且不会出现超时。大多数结果都在 10 秒以下,但这种延迟不是由 FTS 引起的。实际的 FTS 块运行得非常快,正是我们需要对初始 FTS 结果应用的那些额外的 JOIN 和过滤器导致了额外的延迟。

    另一个想法是您的VIEW 可能设计不佳,它没有获得 SQL Server 缓存的执行计划或连接到自身等。要确认这一点,我们需要查看实际的 VIEW 代码,尤其是 JOIN/WHERE 部分.

    【讨论】:

    • 嗨,andrews,我添加了一个示例查询以及我们的视图是什么样的。对探查器大喊大叫。我一直在四处挖掘以查看 FTS 人口报告的时间类型,我看到的时间从几毫秒到一秒多一点,这似乎还不错。我认为 '16 升级即将推出 - 希望这会有所帮助,我注意到最近这些升级的频率大幅上升。
    • @StevenSproat 感谢您的投票。请注意,如果您在 SQL Profiler 中监视 INSERT 调用,那么这些不是 FTS 索引插入,而是基础表 INSERTS。 FTS 监视基表,当 FTS 索引的数据发生更改时,它开始重建实际的 FTS 索引,而您在分析器中看不到它。相反,您会在通过 SSMS 选择 FTS 索引属性或运行类似以下答案的查询时看到它:stackoverflow.com/a/2727952/5857386
    • 保持不变时,FTS 索引填充状态为IDLE,但在重建时,SSMS 将其状态报告为Populating。因此,请尝试监控您的 FTS 索引状态,看看它是否经常重建。
    • @StevenSproat 另一种选择是检查 FTS 索引基表上当前持有的锁。尝试运行此处报告的一些查询:stackoverflow.com/questions/694581/…
    • 再次提出很好的建议,非常感谢。我们不应该在这个表上执行太多的更新或插入 - 我必须检查有多少产品“提要”进入网站,更新库存等。我们使用实体框架,我很确定我们只更新发生变化的属性 - 因此,如果我们收到 3 次相同产品的提要,我很确定我们不会一遍又一遍地更新“描述”,从而导致 FTS 索引每次都重建。给我一个地方看:)
    猜你喜欢
    • 1970-01-01
    • 2014-04-13
    • 1970-01-01
    • 2011-06-10
    • 2021-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多