Sql server 当我使用可变参数而不是常量参数时,为什么我的内联表UDF会慢得多?
我有一个表值的内联自定义项。我想过滤该UDF的结果以获得一个特定值。当我使用常量参数指定过滤器时,一切都很好,性能几乎是瞬时的。当我使用一个可变参数指定过滤器时,它占用的时间要大得多,大约是逻辑读取的500倍和持续时间的20倍 执行计划显示,在可变参数的情况下,直到过程的后期才应用过滤器,导致多个索引扫描,而不是在常量情况下执行搜索 我想我的问题是:既然我指定的是一个对索引字段具有高度选择性的筛选参数,为什么当该参数位于变量中时,我的性能会受到影响?我能做些什么吗 它是否与查询中的分析函数有关 以下是我的疑问:Sql server 当我使用可变参数而不是常量参数时,为什么我的内联表UDF会慢得多?,sql-server,performance,sql-server-2008,user-defined-functions,Sql Server,Performance,Sql Server 2008,User Defined Functions,我有一个表值的内联自定义项。我想过滤该UDF的结果以获得一个特定值。当我使用常量参数指定过滤器时,一切都很好,性能几乎是瞬时的。当我使用一个可变参数指定过滤器时,它占用的时间要大得多,大约是逻辑读取的500倍和持续时间的20倍 执行计划显示,在可变参数的情况下,直到过程的后期才应用过滤器,导致多个索引扫描,而不是在常量情况下执行搜索 我想我的问题是:既然我指定的是一个对索引字段具有高度选择性的筛选参数,为什么当该参数位于变量中时,我的性能会受到影响?我能做些什么吗 它是否与查询中的分析函数有关
CREATE FUNCTION fn_test()
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN
SELECT DISTINCT GCN_SEQNO, Drug_package_version_ID
FROM
(
SELECT COALESCE(ndctbla.GCN_SEQNO, ndctblb.GCN_SEQNO) AS GCN_SEQNO,
dpv.Drug_package_version_ID, ROW_NUMBER() OVER (PARTITION BY dpv.Drug_package_version_id ORDER BY
ndctbla.GCN_SEQNO DESC) AS Predicate
FROM dbo.Drug_Package_Version dpv
LEFT JOIN dbo.NDC ndctbla ON ndctbla.NDC = dpv.Sp_package_code
LEFT JOIN dbo.NDC ndctblb ON ndctblb.SPC_NDC = dpv.Sp_package_code
) iq
WHERE Predicate = 1
GO
GRANT SELECT ON fn_test TO public
GO
-- very fast
SELECT GCN_SEQNO
FROM dbo.fn_test()
WHERE Drug_package_version_id = 10000
GO
-- comparatively slow
DECLARE @dpvid int
SET @dpvid = 10000
SELECT GCN_SEQNO
FROM dbo.fn_test()
WHERE Drug_package_version_id = @dpvid
一旦通过UDF创建了新的投影,就不能期望索引仍然应用于在原始表上编制索引并包含在投影中的列。当您在投影上进行筛选(而不是在UDF中针对原始表进行索引筛选)时,索引将不再适用 您要做的是参数化函数以接受参数
如果您发现要设置参数的字段太多,那么您可能需要查看索引视图,因为您可以创建投影并对其编制索引,然后对其运行查询。简单地说,常量很容易在计划中计算。局部变量不是。特别是使用排序函数和过滤器
谓词=1
套用casparOne的说法,您需要将过滤器尽可能向内推,以便在iq派生表中过滤dpv.Drug\u package\u version\u id
如果您这样做,那么您也不需要使用
分区BY
,因为您只有一个dpv.Drug\u package\u version\u id
。然后你可以做一个清洁剂…顶部1。。。ORDER BY ndctbla.gcnseqnodesc
我得到的回答很好,我从他们那里学到了很多,但我想我找到了一个让我满意的答案
我确实认为是使用partitionby子句导致了这里的问题。我使用自连接习惯用法的变体重新制定了UDF:
SELECT t1.A, t1.B, t1.C
FROM T t1
INNER JOIN
(
SELECT A, MAX(C) AS C
FROM T
GROUP BY A
) t2 ON t1.A = t2.A AND t1.C = t2.C
具有讽刺意味的是,这比使用SQL 2008特定查询的性能更高,而且优化器在使用变量而不是常量连接此版本的查询时也没有问题。在这一点上,我的结论是优化器不能处理较新的SQL扩展以及较旧的东西。作为奖励,我现在可以在预升级的SQL 2000平台中使用UDF
谢谢大家的帮助 有两点——如果我的索引不适用,那么在常量和变量情况下,这不会导致性能低下吗?此外,索引视图是一个好主意,但排名函数会在当前查询状态下排除该问题。@mwigdahl:我已经更新了我的帖子,以说明为什么在投影上筛选时(而不是直接在表上筛选)索引不会应用。另外,您可以创建一个使用排名函数的UDF,然后从索引视图调用它吗?然后创建在索引视图上进行过滤的查询?能否将这两个执行计划都发布到某个位置,以便我可以确切地看到SQL Server在这两种情况下都在做什么?没有理由认为查询语言的新功能将带来更好的性能。他们花了很多时间调整经典表达式。