表值函数 (TVF) 与视图
表值函数和视图有什么区别?有没有什么事情你可以用其中一个来做,而用另一个却很难或不可能做?或者说区别在于效率?
What's the difference between table-valued functions and views? Is there something you can do with 1 that's hard or impossible to do with the other? Or does the difference lie in efficiency?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
无参数内联 TVF 和非物化 View 非常相似。下面是我想到的一些功能差异。
视图
内联 TVF
多语句 TVF
在运行时 视图和内联 TVF 都是内联的,并且处理方式与派生表或 CTE 类似。它们很可能不会被整体评估(甚至在某些情况下根本不会被评估)或者可能在其他情况下被多次评估 。多语句 TVF 将始终被评估并存储在返回表类型(基本上是表变量)
有时,直接参数化内联 TVF 的能力可以比针对视图的等效参数化查询产生更好的执行计划。
A parameterless inline TVF and a non materialized View are very similar. A few functional differences that spring to mind are below.
Views
Inline TVFs
MultiStatement TVFs
At runtime Views and Inline TVFs are both inlined and treated similarly to derived tables or CTEs. They may well not be evaluated in their entirety (or even at all in some cases) or may be evaluated multiple times in others. Multistatement TVFs will always be evaluated and stored in the return table type (basically a table variable)
Occasionally the ability to parameterise inline TVFs directly can lead to a better execution plan than the equivalent parameterised query against a view.
在决定将
SELECT
转换为VIEW
还是TVF
时,我通常有一个经验法则 >。当然,该规则纯粹基于性能。
对于 TVF,我可以使用
CROSS APPLY
,例如将其视为表,但传递特定值,例如主键。性能更快!
如果我有 TVF 的视图,我将不得不允许该视图返回超过 200 万行,只是为了在我的 SELECT 中返回不到 1% 的行。
值得思考的事情。
I generally have a rule of thumb when it comes to deciding whether to convert my
SELECT
to aVIEW
or aTVF
.Of course the rule is purely based on performance.
With a TVF, I can use a
CROSS APPLY
, for example to treat it as a table, but passing a specific value, such as the primary key.Performance is way faster!
If I had a view of the TVF, I would have to allow the view to bring back over 2 million rows just to return less than 1% of that in my SELECTs.
Something to think about.
我发现当在函数的返回表上指定 PK 时,与 MultiStatement TVF 的联接比视图的表现要好得多。
I have found that joins with MultiStatement TVFs perform much better than Views when a PK is specified on the function's return table.
根据我的理解,对此提供不同的看法:
视图
是静态SELECT
语句,而TVF
更接近存储过程 在创建和执行中,您利用输入变量返回动态结果集。常规(内联)TVF 不支持流量控制。如果您需要,那么您需要使用多语句 TVF。也就是说,您也可以从
存储过程
INSERT
到表变量中,这就是TVF以更优雅的方式所做的事情,不需要<代码> EXEC权限。从可维护性的角度来看,我更喜欢 TVF,因为我不必编写多个查询来获取各种结果,也不必从视图中进行过滤(即 SELECT * FROM [view] WHERE [conditions]) 。在 TVF 中,我可以利用索引更快地返回较小的结果集。要在视图中执行此操作,您必须预先了解查询每次将执行的操作,并硬指定过滤条件。如果您要做的只是从过去 6 个月内输入的表中选择数据子集,那么视图就可以正常工作,因为您只需编写:
为了性能,您显然希望索引
[date_col]
因此视图运行得更快。To offer a different take on this, from my understanding:
Views
are staticSELECT
statements whereasTVFs
are closer toStored Procedures
in both creation and execution in that you return a dynamic result set leveraging input variables. Regular (Inline) TVFs don't support flow control. If you need that then you need to use the Multi-Statement TVF. That said, you could also just as wellINSERT
into a table variable from aStored Procedure
which is what the TVF is doing in a more elegant way that doesn't needEXEC
permissions.From a maintainability perspective, I perfer TVFs as I don't have to write several queries to get various results or have to filter from a View (i.e.,
SELECT * FROM [view] WHERE [conditions]
). In the TVF, I can leverage the indexes for returning smaller result sets faster. To do this in a view, you would have to have advance knowledge of what the query is going to do every time and hard specify the filtering conditions. If all you're going to do is select a subset of data from a table that was entered in the last 6 months, then a view would work fine as you can just write:For performance you'd obviously want to index
[date_col]
so the view would run faster.