表值函数 (TVF) 与视图

问题描述 投票:0回答:4

表值函数和视图有什么区别?有没有什么事情你可以用其中一个来做,而用另一个却很难或不可能做?还是效率不同?

sql-server sql-view sql-function
4个回答
151
投票

无参数内联 TVF 和非物化 View 非常相似。下面是我想到的一些功能差异。

观点

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  

内联 TVF

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    

多语句 TVF

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    

在运行时,视图和内联 TVF 都是内联的,并且处理方式与派生表或 CTE 类似。它们很可能不会被整体评估(或者在某些情况下甚至根本不会被评估)或者在其他情况下可能会被多次评估。多语句 TVF 将始终被评估并存储在返回表类型(基本上是表变量)中

有时,直接参数化内联 TVF 的能力可以产生比针对视图的等效参数化查询更好的执行计划。


10
投票

在决定是否将我的 SELECT 转换为

VIEW
TVF
时,我通常有一个
 经验法则

该视图是否需要超过 2 秒才能完成? 超过 10,000 条记录?如果是,则将其转换为 TVF。如果没有,就留下它 一个人。

当然,该规则纯粹基于表现

使用 TVF,我可以使用

CROSS APPLY
,例如将其视为表格,但传递特定值,例如 主键

WHERE ID = xxx
,其中“xxx”是我在 SELECT 中传递的值。

性能更快!

如果我有 TVF 的视图,我将不得不允许视图带回超过 200 万行,只是为了在我的 SELECT 中返回不到 1%。

需要思考的事情。


2
投票

我发现,当在函数的返回表上指定 PK 时,与 MultiStatement TVF 的连接性能比视图好得多。

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

0
投票

根据我的理解,对此提供不同的看法:

Views
是静态
SELECT
语句,而
TVFs
在创建和执行方面更接近于
Stored Procedures
,因为您利用输入变量返回动态结果集。常规(内联)TVF 不支持流量控制。如果您需要,那么您需要使用多语句 TVF。也就是说,您也可以从
INSERT
到表变量
Stored Procedure
,这就是 TVF 正在以一种更优雅的方式所做的事情,它确实需要
EXEC
权限。

从可维护性的角度来看,我更喜欢 TVF,因为我不必编写多个查询来获取各种结果,也不必从视图中进行过滤(即

SELECT * FROM [view] WHERE [conditions]
)。在 TVF 中,我可以利用索引更快地返回较小的结果集。要在视图中执行此操作,您必须预先了解查询每次将要执行的操作,并硬指定过滤条件。如果您要做的只是从过去 6 个月内输入的表中选择数据子集,那么视图就可以正常工作,因为您只需编写:

SELECT [columns]
FROM [schema].[table]
WHERE [date_col] >= CAST(DATEADD(m,-6,GETDATE()) AS DATE)

为了性能,您显然需要索引

[date_col]
,以便视图运行得更快。

© www.soinside.com 2019 - 2024. All rights reserved.