表值函数和视图有什么区别?使用表值函数可能做到的事情,在视图中是否难以或不可能实现?还是两者之间的区别在于效率?
表值函数和视图有什么区别?使用表值函数可能做到的事情,在视图中是否难以或不可能实现?还是两者之间的区别在于效率?
一个没有参数的内联表值函数和一个非物化的视图非常相似。下面是我想到的一些功能上的差异。
Accepts Parameters - No
Expanded out by Optimiser - Yes
Can be Materialized in advance - Yes (through indexed views)
Is Updatable - Yes
Can contain Multiple Statements - No
Can have triggers - Yes
Can use side-effecting operator - Yes
Accepts Parameters - Yes
Expanded out by Optimiser - Yes
Can be Materialized in advance - No
Is Updatable - Yes
Can contain Multiple Statements - No
Can have triggers - No
Can use side-effecting operator - No
Accepts Parameters - Yes
Expanded out by Optimiser - No
Can be Materialized in advance - No
Is Updatable - No
Can contain Multiple Statements - Yes
Can have triggers - No
Can use side-effecting operator - No
在运行时,视图和内联表值函数(Inline TVF)都会被内联处理,并且类似于派生表或公共表表达式(CTE)。它们可能不会完全评估(甚至在某些情况下根本不评估),在其他情况下可能会被多次评估。多语句表值函数(Multistatement TVF)始终会被评估并存储在返回表类型中(基本上是一个表变量)。
当我需要决定是将我的SELECT
转换为VIEW
还是TVF
时,我通常有一个经验法则。
视图是否需要超过2秒才能完成,并且记录数超过10,000条? 如果是,将其转换为TVF。 否则,请不要改变它。
当然,这个规则纯粹基于性能。
使用TVF,例如使用CROSS APPLY
,可以像处理表一样处理它,但传递特定的值,例如主键。
WHERE ID = xxx
,其中'xxx'是我在SELECT中传递的值。
性能更快!
如果我有一个视图或TVF,我必须允许视图带回超过2百万行,只返回我的SELECTs中不到1%的内容。
值得思考。
我发现当函数的返回表上指定了PK时,与MultiStatement TVFs连接比视图执行效果要好得多。
CREATE FUNCTION [FORMREQS].[fnGetFormsStatus] ()
RETURNS
/* Create a PK using two of the columns */
@Indexed TABLE (
[OrgID] [char](8) NOT NULL,
[PkgID] [int] NOT NULL,
[FormID] varchar(5) NOT NULL,
PRIMARY KEY CLUSTERED(OrgID, PkgID)
)
AS
BEGIN
INSERT @Indexed SELECT OrgID, PkgID, FormID FROM FormsTable
RETURN
END
RETURNS
子句的函数不需要创建任何临时表,因此它将至少运行两倍快。可能会更快,因为优化器将能够将其查询包含在优化中。 - Panagiotis Kanavos
with check option
和VIEW_METADATA
。 - Martin Smith