用户定义的功能性能缺点

Fis*_*ury 3 sql sql-server performance function user-defined-functions

我有一个包含大量UDF的数据库,其中包含一个涉及大量数据操作和计算的长时间运行的进程.

我在使用UDF时的想法是从基础表中分离出逻辑信息单元.例如,如果我试图获取有关汽车的信息,我可能会有几个表格,如颜色,模型,年份等,我每次都必须加入汽车.相反,我会有一个像fnCar()这样的函数来获取数据的非规范化视图.

在我长时间运行的过程中,我经常调用这些函数,我想知道如果我有一个非规范化的工作表,视图或临时表来进行数据操作和计算会更好.使用UDF一般有什么不利之处,我应该注意性能方面的问题?

例如,我使用UDF进行一些计算.然后我将数据取消存储并存储在表中.每当我需要再次使用该数据时,我调用UDF来将数据转回.我们这样做的原因是为了保持我们的计算灵活性.如果我们添加/删除/更改计算,我们不想更改数据模型.

--Calculate some values in a function

declare @location table
(
    id int,
    lattitude float,
    longitude float
)

insert into @location select  1, 40.7, 74
insert into @location select  2, 42, 73
insert into @location select  3, 61, 149
insert into @location select  4, 41, 87


declare @myLattitude float
declare @myLongitude float
set @myLattitude =43
set @myLongitude = 116

declare @distance table
(
    id int,
    distance float
)

insert into @distance
select id, sqrt(power(lattitude-@mylattitude,2)+power(longitude-@mylongitude,2))
from @location



--Store unpivoted data in a table
declare @unpivot table
(
    id int,
    attribute varchar(100),
    attributeValue float
)

insert into @unpivot
(
    id,
    attribute,
    attributeValue
)
select id
    ,attribute
    ,attributevalue 
from
(
    select 
        L.id,
        L.Lattitude, 
        L.Longitude,
        D.Distance
    from @location L 
        inner join @distance D 
        on L.id=D.id
) a
unpivot 
(
    attributeValue for attribute in
    (lattitude, longitude, distance)
) x

--retrive data from store via pivoting function for reporting

select * 
from @unpivot
pivot 
(
    max(attributeValue) for Attribute in (lattitude, longitude, distance)

) x
Run Code Online (Sandbox Code Playgroud)

gbn*_*gbn 6

我会尝试一个答案

简单地说:你在使用UDF时做错了

使用UDF时,则会添加这些问题

  1. RBAR(参见下图)处理
    当您在SELECT子句中使用带有表访问权限的标量UDF时
    ,而不是有效的JOIN,而是强制每行使用一个表lookip*

  2. 使用多语句
    TVF进行黑匣子处理每个TVF必须运行完成并被视为"黑匣子"

通常做的是加载一个平面的临时表,然后加入查找表,处理作为一个集完成.如果你的意思是"非规范化",那么是的,它可能会更好.

将UDF用于"逻辑信息单元"是OO /程序思维.SQL是基于设置的.对于通过查询优化器进行的基于集合的数据处理,在本机/ CLR代码中运行的对象或对象集合看起来没问题.

注意:RBAR =行按Agonizing Row.有关更多信息,请参阅Simple Talk的文章

  • @FistOfFury:*内联*TVF只是一个像视图一样扩展的宏.因此,您可以隐藏JOIN的数量,但要避免RBAR处理 (3认同)
  • @GordonLinoff:内联TVF和非索引视图在SQL Server中的行为相同 (3认同)
  • 如果我们想要封装数据的特定视图,那么"视图"是正确的方法,而不是UDF.但是如果没有关于如何使用它们的更多信息,那么很难进行概括. (2认同)