在我看来,我遇到了以下非常奇怪的问题。当我通过以下方式调用UDF时:
DECLARE @contact_id uniqueidentifier
DECLARE @group_id uniqueidentifier
SET @group_id = 'EE57E2AD-204B-4078-AFA4-11FA8375C2FD'
set @contact_id = 'E6EFCC9F-9D1C-4C38-A950-C45372F2A6D2'
SELECT COUNT( ID ) AS [CountAll]
FROM [Document] As [Document]
WHERE ([Document].[ID] IN (SELECT ID FROM [fs_Document_View_ee57e2ad_204b_4078_afa4_11fa8375c2fd](@contact_id, @group_id)))
它运行了 4 秒,我得到以下执行计划: 快速
当我使用硬编码参数调用UDF时:
SELECT COUNT( ID ) AS [CountAll]
FROM [Document] As [Document]
WHERE ([Document].[ID] IN (SELECT ID FROM [fs_Document_View_ee57e2ad_204b_4078_afa4_11fa8375c2fd]('E6EFCC9F-9D1C-4C38-A950-C45372F2A6D2', 'EE57E2AD-204B-4078-AFA4-11FA8375C2FD')))
我得到了这个执行计划:慢,需要 91 秒。
谁能解释我为什么会这样?
该函数调用 4 个其他嵌套函数,向它们传递相同的参数。它与项目查看权限有关。
我在这里先向您的帮助表示感谢。
更新
我使用了 Ivan G. 提到的这篇文章中的选项 2。
问题是参数嗅探,选项 2 解决了这个问题。
解决参数嗅探问题的另一种方法是完全禁用参数嗅探。这不是通过开关或数据库选项来完成的,但可以在存储过程代码的脚本中完成。这是我如何创建 > 存储过程以禁用参数嗅探的示例:
DROP PROC [dbo].[DisplayBillingInfo]
GO
CREATE PROC [dbo].[DisplayBillingInfo]
@BeginDate DATETIME,
@EndDate DATETIME
WITH RECOMPILE
AS
DECLARE @StartDate DATETIME;
DECLARE @StopDate DATETIME;
SET @StartDate = @BeginDate;
SET @StopDate = @EndDate;
SELECT BillingDate, BillingAmt
FROM BillingInfo
WHERE BillingDate between @StartDate AND @StopDate;
要禁用参数嗅探,我所做的只是更改在存储过程中使用参数值的方式。通过在我的过程中创建两个不同的局部变量(@StartDate 和@EndDate),将这些变量设置为传递的参数,然后在 BETWEEN 条件中使用局部变量,我能够禁用参数嗅探。参数嗅探被禁用,因为优化器无法识别实际 SELECT 语句中的参数值。因为 SQL Server 无法判断在哪里调用存储过程的参数值,所以优化器会根据统计信息创建一个通用计划。
当我使用上面的代码执行我的存储过程时,使用一个狭窄的日期范围或一年的日期,编译的执行计划总是执行“索引扫描”操作。我可以告诉参数嗅探已关闭,因为我知道较短的日期范围通常会创建索引查找操作。