【问题标题】:How can I optimize this horrendously inefficient User Defined Function in SQL Server 08如何在 SQL Server 08 中优化这个极其低效的用户定义函数
【发布时间】:2010-10-19 22:19:10
【问题描述】:

有没有办法在 SQL Server 08 中优化这个可怕的低效 UDF。我对 UDF 还很陌生,尤其是在寻找优化。

更新: 如果我想在查询中的每一行和每一列上执行它,我应该将一列发送到这样的函数吗?有没有更好的方法来解决这个问题?

谢谢

** @value(float) 和@fieldname(varchar(40)) 是输入参数**

BEGIN
  DECLARE @UT integer, @FRM integer, @TO integer, @FACTOR float

  select @UT =  [UF_UT_ID] FROM dbo.UNIT_FIELDS where [UF_FIELD]=@fieldName
  select @FRM = [UT_UN_ID_INTERNAL_UNITS] from dbo.UNIT_TYPES where [UT_ID]=@UT
  select @TO = [UT_UN_ID_DISPLAY_UNITS] from dbo.UNIT_TYPES where [UT_ID]=@UT
  select @FACTOR = [UC_SLOPE] from dbo.UNIT_CONVERSIONS where [UC_UN_ID_UNIT_FROM]=@FRM and [UC_UN_ID_UNIT_TO]=@TO

  -- Return the result of the function dbo.
  RETURN @FACTOR*@value
END

【问题讨论】:

  • 你怎么知道这个UDF效率低?你在 SQL Profiler 中看到了什么?

标签: sql sql-server-2008 user-defined-functions


【解决方案1】:

如果您可以根据 PK/FK 关系连接三个表,则可以将查询简化为单个选择。如果没有,唯一明显的优化是在单个 select 语句中分配 @FRM 和 @TO:

select @FRM = [UT_UN_ID_INTERNAL_UNITS], @TO = [UT_UN_ID_DISPLAY_UNITS] from dbo.UNIT_TYPES where [UT_ID]=@UT

【讨论】:

    【解决方案2】:

    内联表函数的经典候选...

    类似:

    ALTER FUNCTION fnName(@value float, @fieldName VARCHAR(100))
    RETURNS TABLE 
    AS
    RETURN 
    (
        SELECT @value * 
            (SELECT conv.[UC_SLOPE] from dbo.UNIT_CONVERSIONS conv
            JOIN dbo.UNIT_TYPES UT_UN_ID_INTERNAL_UNITS ON where [UC_UN_ID_UNIT_FROM]=UT_UN_ID_INTERNAL_UNITS.[UT_ID]
            JOIN dbo.UNIT_TYPES UT_UN_ID_DISPLAY_UNITS ON where [UC_UN_ID_UNIT_TO]=UT_UN_ID_DISPLAY_UNITS.[UT_ID]
            JOIN dbo.UNIT_FIELDS fields ON (UT_UN_ID_INTERNAL_UNITS.[UT_ID] = fields.[UF_UT_ID]) AND (UT_UN_ID_DISPLAY_UNITS.[UT_ID] = fields.[UF_UT_ID])
            WHERE ([UF_FIELD]=@fieldName)
            )
    )
    

    【讨论】:

      【解决方案3】:

      第 1 步是单独运行每个选择并查看瓶颈在哪里。

      【讨论】:

        【解决方案4】:

        你可以做的一件小事:

         select @FRM = [UT_UN_ID_INTERNAL_UNITS] from dbo.UNIT_TYPES where [UT_ID]=@UT  
         select @TO = [UT_UN_ID_DISPLAY_UNITS] from dbo.UNIT_TYPES where [UT_ID]=@UT 
        

        如果我没看错的话,应该是这样的:

         select @TO = [UT_UN_ID_DISPLAY_UNITS],
                @FRM = [UT_UN_ID_INTERNAL_UNITS] 
        
         from dbo.UNIT_TYPES where [UT_ID]=@UT 
        

        为什么要在同一条记录上运行两次选择?

        【讨论】:

          【解决方案5】:

          这需要使用JOIN's 重写:

          SELECT  c.UC_SLOPE * @value
          FROM    unit_fields f
          JOIN    unit_types t
          ON      t.UT_ID = f.UF_UT_ID
          JOIN    unit_conversions c
          ON      c.UC_UN_ID_UNIT_FROM = t.UT_UN_ID_INTERNAL_UNITS
                  AND c.UC_UN_ID_UNIT_TO = t.UT_UN_ID_DISPLAY_UNITS
          WHERE   f.UF_FIELD = @field_name
          

          【讨论】:

            【解决方案6】:
            BEGIN
              DECLARE @FACTOR float
            
                select @factor = UC.UC_SLOPE
                  from dbo.UNIT_CONVERSIONS UC,
                       dbo.UNIT_TYPES       UT,
                       dbo.UNIT_FIELDS      UF
                  where UF.UF_FIELD=@fieldName
                    and UT.UT_ID = UF.UF_UT_ID
                    and UC.UC_UN_ID_UNIT_FROM = UT.UT_UN_ID_INTERNAL_UNITS
                    and UC.UC_UN_ID_UNIT_TO = UT.UT_UN_ID_DISPLAY_UNITS
            
            
              -- Return the result of the function dbo.
              RETURN @FACTOR*@value
            END
            

            【讨论】:

              【解决方案7】:

              您可以将其作为一个查询来尝试:

              --Decalre Factor var
              DECLARE @FACTOR float
              
              SELECT @FACTOR = [UC_SLOPE] 
              FROM dbo.UNIT_CONVERSIONS uc
              --Join the Unit Types table to Unit Conversions on the old From & To types
              INNER JOIN dbo.UNIT_TYPES ut ON
                  ut.[UT_UN_ID_DISPLAY_UNITS] = uc.[UC_UN_ID_UNIT_TO]
                  AND ut.[UT_UN_ID_INTERNAL_UNITS] = uc.[UC_UN_ID_UNIT_FROM]
              --Join the Unit Files on the Unit Types
              INNER JOIN dbo.UNIT_FIELDS uf ON
                  uf.[UF_UT_ID] = ut.[UT_ID]
              WHERE uf.[UF_FIELD]=@fieldName
              
              -- Return the result of the function dbo.
              RETURN @FACTOR*@value
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2016-07-16
                • 2018-06-30
                • 2015-07-19
                • 2016-11-25
                • 1970-01-01
                • 1970-01-01
                • 2015-01-05
                • 2019-06-10
                相关资源
                最近更新 更多