我的情况非常简单:
我有一个名为FullTextPagina
的表值函数定义如下:
select * from Pagina as p where contains(p.PageText, @term)
然后我有2个查询:
declare @term nvarchar(4000)= N'"DIEGO NUNES J COMBINADO"'
SELECT Id, DtPagina
FROM FullTextPagina(@term)
ORDER BY DtPagina DESC
SELECT TOP 10 Id, DtPagina
FROM FullTextPagina(@term)
ORDER BY DtPagina DESC
除了第二个包含TOP 10
语句之外,它们是相同的。并且他们不会返回任何东西。 0行。
第一个立即执行。秒需要1:20米才能完成。
为什么?
PS:
DtPagina
修改
回应@MartinSmith,奇怪的是,表值函数的“执行次数”对于TOP 10案例是118万,对于另一案例是1
编辑2
执行计划XML http://tecnologia.novaprolink.com.br/Execution%20plan.xml
编辑3
添加选项(重新编译)或取消参数不会影响结果
SELECT Id, DtPagina
FROM FullTextPagina(N'"DIEGO NUNES J COMBINADO"')
ORDER BY DtPagina DESC
SELECT TOP 10 Id, DtPagina
FROM FullTextPagina(N'"DIEGO NUNES J COMBINADO"')
ORDER BY DtPagina DESC
OPTION (RECOMPILE)
编辑4
FullTextPagina
USE [RexConsumo_2011_11]
GO
/****** Object: UserDefinedFunction [dbo].[FullTextPagina] Script Date: 11/24/2011 11:43:09 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[FullTextPagina] (@term nvarchar(4000))
RETURNS TABLE
AS
RETURN
(
select * from Pagina as p where contains(p.PageText, @term)
)
GO
答案 0 :(得分:5)
您遇到的问题是因为SQL Server无法准确估计与谓词匹配的行数。
您的查询正在执行SELECT TOP 10 Id, DtPagina ... ORDER BY DtPagina DESC
。关于它如何做到这一点有几个选择
它可以按顺序扫描DtPagina DESC
索引并查看每一行是否与全文谓词匹配,然后在找到索引顺序中的前10个时退出。
DtPagina
列值当计算第一个选项时,底部计划显示它必须扫描大约600行才能获得10个匹配并且能够退出。这是一个大规模的低估,因为实际上没有行匹配谓词,它需要为整个1,186,533行执行此操作。
当从顶层计划中计算第二个选项时,可以看出它假定有13846.2个匹配的行将从全文索引查询中返回并需要加入和排序。由于实际数字为零,这是一个很大的估计值。
因此,这些不正确的估计导致它错误地支持第一个选项。
我不确定如何提高全文索引统计信息的准确性。也许尝试使用containstable
编辑:这有点像黑客但可能会有效。如果你尝试
怎么办?declare @term nvarchar(4000)= N'"DIEGO NUNES J COMBINADO"'
declare @num int = 10
SELECT TOP (@num) Id, DtPagina
FROM FullTextPagina(@term)
ORDER BY DtPagina DESC
然后它会假设TOP 100
,这可能足以让他们选择其他更有效的计划。