Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 为什么我的特定用户定义函数非常慢?_Sql Server_Sql Server 2008_Tsql_User Defined Functions_Database Performance - Fatal编程技术网

Sql server 为什么我的特定用户定义函数非常慢?

Sql server 为什么我的特定用户定义函数非常慢?,sql-server,sql-server-2008,tsql,user-defined-functions,database-performance,Sql Server,Sql Server 2008,Tsql,User Defined Functions,Database Performance,从开始:X可以有零个或多个Y;X与特定的Z相关联 我的函数计算所有X,而不计算与特定Z关联的Y;这是我的自定义项功能: ALTER FUNCTION [dbo].[CountXWithNoYByZ] ( @zUID int ) RETURNS int AS BEGIN DECLARE @result int IF (@zUID IS NULL) RETURN -1; SET @result = ( SELECT COUNT(DISTINCT X.UID)

从开始:X可以有零个或多个Y;X与特定的Z相关联

我的函数计算所有X,而不计算与特定Z关联的Y;这是我的自定义项功能:

ALTER FUNCTION [dbo].[CountXWithNoYByZ]
(
    @zUID int
)
RETURNS int
AS
BEGIN

DECLARE @result int

IF (@zUID IS NULL)
    RETURN -1;

SET @result = 
(
    SELECT COUNT(DISTINCT X.UID)
    FROM X
    INNER JOIN XZ ON X.UID = XZ.X_UID
    LEFT JOIN Y ON X.UID = Y.X_UID
    WHERE (Y.UID IS NULL) AND (XZ.Z_UID = @zUID)
)

RETURN @result
END
此功能的用法:

 DECLARE @myCount int
 SET @myCount = dbo.CountXWithNoYByZ(@zUID)
 SELECT @myCount
当我将此函数用作标量函数时,它的速度非常慢(对于X表中的10000条记录和Y表中的20000条记录,速度分别为8秒和8秒),但在外部(<1秒)使用时,速度就不慢了。为什么?

注意:
SELECT
中使用UDF时,我意识到它的速度有些慢,因为它会为每一行运行,但我不会在
SELECT
中使用它;为了便于统计,它将与存储过程中的
SET
组合运行一次(与其他没有性能问题的函数一起运行)

编辑:嗯,我重新启动了SQL Server,现在速度更快了,但这并不意味着案件已经解决

我是新来的,但我想附上执行计划。。。希望有帮助!
我注意到的一些想法/事情:

  • 您的查询计划具有用于其信息检索的所有扫描(而不是任何搜索)。就性能而言,索引扫描实际上只比表扫描稍微好一点,“聚集索引扫描”是表扫描。将此计划与联机运行SQL语句而不是作为函数运行时得到的计划(可能效率更高)进行比较会很有趣

  • 接受答案)在这种情况下,查询的性能因运行方式的不同而有很大差异,这可能是因为分布不均的数据和缓存的查询计划之间存在邪恶的联盟。一点背景:SQLServer支持一种称为“参数嗅探”的优化,它将根据查询中的特定值选择不同的计划。如果你说“WHERE bread='Pomeranian'”只有5个,它将使用一个计划,但如果你说“WHERE bread='Mutt'”有10000个,它将使用不同的计划。当参数嗅探没有发生时,问题就出现了,导致将博美拉尼亚计划应用于mutt查询。对于函数和存储过程,如果要确保参数嗅探,必须在每次执行时强制重新编译计划。(不过,这本身是有代价的,因此只有在由于这个特定原因而出现已知的性能问题时,才应该这样做。)对于函数,可以在相关查询中包含“重新编译”提示;对于存储过程,可以在CREATEPROC语句中指定“WITHRECOMPILE”。非常好的链接

  • 您可以为查询结构本身尝试一些不同的方法——如果连接创建了一堆重复的结果,而DISTINCT又将它们全部扔掉,那么JOIN+DISTINCT可能会占用资源。这在您的情况下尤其可能——当您实际上对连接成功的任何一行都不感兴趣时,为什么要连接到这些Y行中的每一行?“notexists”可能更快(取决于我们正在谈论的不必要的连接子行的数量),因为它将在找到第一个匹配项后立即停止尝试连接

  • 大概是这样的:

    SELECT X.UID
    FROM X
      INNER JOIN XZ ON X.UID = XZ.X_UID
    WHERE (XZ.Z_UID = @zUID)
      AND NOT EXISTS (SELECT 1 FROM Y WHERE X.UID = Y.X_UID)
    

    您必须进行一些基准测试,因为根据您的数据,这当然也可能会导致性能下降

    关于这一点,我要问的主要问题是,如果要将UDF包装到存储过程中,为什么还要麻烦它呢?但是假设有必要,这里有一些资源可以帮助您:您的查询计划是什么样子的?你有索引吗?我计划从多个过程中重用这个函数。是的,UID是这些表中的索引。如前所述,只有当代码用作函数时,它才会变慢。按原样使用时速度很快。很奇怪!为我们提供查询计划作为索引存在和使用的证明。@SimonSvensson:对于XZ表,我只有一个聚集索引:X_UID(ASC),Z_UID(ASC)-主键。。。这可能是个问题吗?非常感谢你的想法。。。非常感谢。。。我会根据你的意见尝试更多。你真是太棒了!这个“重新编译”的把戏帮了我!请将此链接添加到您的答案。。。这对理解我的奇怪行为很有帮助。