Pet*_*ter 6 sql-server execution-plan sql-server-2016
我有一个涉及全文搜索的查询,如下所示:
SELECT TOP 30 PersonId,
PersonParentId,
PersonName,
PersonPostCode
FROM dbo.People
WHERE PersonDeletionDate IS NULL
AND PersonCustomerId = 24
AND CONTAINS(ContactFullText, '"mr" AND "ch*"')
AND PersonGroupId IN(197, 206, 186, 198)
ORDER BY PersonParentId,
PersonName;
Run Code Online (Sandbox Code Playgroud)
这会生成两个主要计划,一个在所有情况下都非常快,另一个在大多数情况下非常慢。
我已经尝试过这个查询,这样就没有包括 FT 搜索,我发现行估计总是比它们应该的低。
如果我运行,update statistics...with fullscan
我仍然会在执行计划中看到来自 NC 索引查找操作的极不准确的行估计。
当行估计值足够低时,会选择循环连接,这通常非常慢(30 秒以上)。更高的估计似乎会产生一个很好的计划,涉及合并连接而不是循环连接。
尽管仍有最新的统计信息,为什么 SQL Server 仍然不估计行数?
计划:https : //www.brentozar.com/pastetheplan/?id=rkXtE0jzX
当我删除该CONTAINS
部分,从而省略全文搜索时,查询速度很快,但索引查找的行估计仍然是 1 估计,实际为 2195。
根据@Kin 的建议,我使用了 CONTAINSTABLE,它立即运行并生成了以下计划:https : //www.brentozar.com/pastetheplan/? id =S1hKainzQ有趣的是没有全文搜索运算符。
RANK
在这种情况下,Containstable 需要生成相同的结果集,我已经使用AND RANK > 0
它WHERE
来生成我想要的结果,从而生成此计划:https : //www.brentozar.com/pastetheplan/?id=B1U7AA2zm
我现在唯一的问题是为什么行估计仍然不准确,但我现在不太关心我的 FT 查询似乎更快更可靠。很高兴! https://www.brentozar.com/pastetheplan/?id=B1U7AA2zm
@EvanCarroll 统计直方图在这里:https ://pastebin.com/p7s0NvX5
一些后续信息 - 支持的应用程序的一些典型 FT 搜索查询的执行计划之前/之后
一种
乙
C
D
(总结我的评论并作为答案)
查询重写将解决行估计值较低的问题。正如 Joe Chang 在他的博客文章 《查询优化器狂野》中所解释的那样 - 全文
根据 Microsoft 文档,CONTAINS 是“WHERE 子句中使用的预测”,而 CONTAINSTABLE 充当表。
使用与实际计划相比,使用使用具有低行估计的嵌套循环连接可以获得更好的计划(合并连接)。CONTAINSTABLE
contains
您可以将查询重写为:
SELECT TOP 30 p.PersonId,
p.PersonParentId,
p.PersonName,
p.PersonPostCode
FROM dbo.People p
left join containstable (ContactFullText, '"mr" AND "ch*"') cf on cf.[yourKey] = p.PersonId
WHERE p.PersonDeletionDate IS NULL
AND p.PersonCustomerId = 24
--AND CONTAINS(ContactFullText, '"mr" AND "ch*"')
AND p.PersonGroupId IN(197, 206, 186, 198)
AND [RANK] > 0
ORDER BY p.PersonParentId,
p.PersonName;
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
976 次 |
最近记录: |