【发布时间】:2015-06-10 17:22:30
【问题描述】:
我想为我的标量函数制定一个执行计划,因为它与我只运行一个函数体时的执行计划不同。前段时间我也遇到过同样的情况,我通过对索引进行碎片整理来解决它(由于高碎片,函数没有使用碎片索引,但纯查询使用了)。但现在我的碎片
我可以得到正确的估计执行计划,但是当我想得到一个实际的计划时, 我几乎一无所获。
所以在这里我只得到了无用的外部查询计划,但看不到函数中发生了什么。
可以修复吗?
预计执行计划:
<ParameterList>
<ColumnReference Column="@DateTo" ParameterCompiledValue="NULL" />
<ColumnReference Column="@DateFrom" ParameterCompiledValue="NULL" />
<ColumnReference Column="@ServerID" ParameterCompiledValue="NULL" />
<ColumnReference Column="@ResourceTypeID" ParameterCompiledValue="NULL" />
</ParameterList>
我找到了函数的实际执行计划(感谢 Sql Server Profiler)
纯查询的实际计划(快速): 功能(慢):
这个函数只是从表中取出一些 XML 字段并将它们连接到一个大的 XML 文件中:
ALTER FUNCTION [dbo].[fn_GetErrorXML]
(
@DateFrom datetime,
@DateTo datetime,
@ResourceTypeID bigint,
@ServerID int
)
RETURNS NVARCHAR(MAX)
AS
BEGIN
DECLARE @ErrorDescription VARCHAR(MAX)
SET @ErrorDescription = '<root>';
WITH CTE AS
(
SELECT
d.GeneratedOnUtc,
ErrorDescription = cast(d.Data as nvarchar(max))
FROM dbo.AgentData d
INNER JOIN dbo.Agent a ON a.CheckID = d.CheckID
INNER JOIN dbo.Server s ON a.ServerID = s.ID
WHERE d.EventType = 'Result' AND
a.ResourceTypeID & @ResourceTypeID > 0 AND
s.ID = @ServerID AND
d.GeneratedOnUtc between @DateFrom AND @DateTo AND
d.Result = 0
)
SELECT @ErrorDescription = @ErrorDescription + cte.ErrorDescription
FROM CTE
ORDER BY cte.GeneratedOnUtc ASC
RETURN(@ErrorDescription + '</root>')
END
【问题讨论】:
-
可能是参数嗅探。您可能会从缓存中提取计划并查看它使用哪些参数进行编译,然后通过将逻辑放入存储过程并首先使用这些参数值执行它,然后再使用问题中显示的参数值来重现问题。
-
您还可以使用分析器或扩展事件检索实际计划。这里讨论了这种行为的原因dba.stackexchange.com/a/29749/3690
-
@MartinSmith,你能详细解释一下吗?
-
在估计的计划中你能不能把它看成XML,看到
ParameterCompiledValues? -
这绝对是内联表值函数的完美候选者。
标签: sql sql-server sql-server-2008-r2 sql-execution-plan