分页时SQL Server查询变慢


14

我在SQL Server 2012中看到以下T-SQL查询的某些奇怪行为:

SELECT Id 
FROM dbo.Person 
WHERE CONTAINS(Name, '"John" AND "Smith"')
ORDER BY Name

仅执行此查询即可在不到两秒钟的时间内获得约1,300个结果(上有全文索引Name

但是,当我将查询更改为此:

SELECT Id 
FROM dbo.Person 
WHERE CONTAINS(Name, '"John" AND "Smith"')
ORDER BY Name
OFFSET 0 rows
FETCH NEXT 10 ROWS ONLY

给我10个结果需要20秒钟以上。

以下查询甚至更糟:

SELECT Id 
FROM ( 
    SELECT ROW_NUMBER() OVER (ORDER BY Name) AS RowNum, Id 
    FROM dbo.Person
    WHERE CONTAINS(Name, '"John" AND "Smith"') ) AS RowConstrainedResult 
WHERE RowNum >= 0 AND RowNum < 11 
ORDER BY RowNum

需要超过1.5分钟才能完成!

有任何想法吗?

慢计划

慢

快速计划

快速


如果将第二个查询更改为,会发生什么SELECT TOP 10 * .... ORDER BY Name
拉马克2012年

索引IX_PersonSearch ...在哪些列上进行?因为从表中选择*,并且使用的索引不包含所有输出列,所以您正在进行键查找。我认为您应该只选择所需的列,然后将它们包含在非聚集索引中作为包含的列,而不是索引列。
Marcel N.

您可以在表上发布索引(创建脚本)吗?

3
该ID始终包含在每个非聚集索引中。这是SQL Server能够(通过ID)键入查找键的方法。
usr

1
我忘了提的是:当我用LIKE而不是CONTAINS进行相同的查询时,速度也很快。(是否分页)

Answers:


7

正如您只想TOP 10按名称排序一样,它认为name按顺序向下处理索引并查看每行是否与CONTAINS(Name, '"John" AND "Smith"') )谓词匹配会更快。

大概需要更多的行才能找到所需的10个匹配项,然后再预期,并且此基数问题与键查找的数量更为复杂。

使用此计划阻止它的一个快速技巧是将更ORDER BY改为,ORDER BY Name + ''尽管CONTAINSTABLE与结合使用FORCE ORDER也应该可以。


3

这看起来像经典的选择性估计错误。不确定由于查询的“驱动程序”是全文搜索,因此无法使用统计信息进行扩充。

尝试将where contains谓词重写为inner join containstableCONTAINSTABLE),并应用连接顺序提示以强制计划的形状。

这不是一个完美的解决方案,因为它存在维护问题,但是我看不到其他方法。


感谢您的回答,我尝试了。但是,结果相同:不使用分页时,查询速度很快。分页时突然又变慢了:/

好的,您可以将计划作为图像和查询发布吗?我猜想我们还没有成功生成所需的形状。
usr 2012年

3

我设法解决了这个问题:

就像我在问题中说的那样,所有列上都有索引,每列都有统计信息。(由于使用了传统的LIKE查询),我删除了所有索引和统计信息,添加了全文本搜索和文本,查询变得非常快。

似乎印度人提出了不同的执行计划。

非常感谢大家的帮助!


1
好吧,完全删除该索引是防止它被使用的一种方法!
马丁·史密斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.