【问题标题】:Table-Valued Function(TVF) vs. View表值函数 (TVF) 与视图
【发布时间】:2011-06-25 00:18:27
【问题描述】:

表值函数和视图有什么区别?有什么事情你可以用 1 做而另一个很难或不可能做吗?还是说效率上的区别?

【问题讨论】:

    标签: sql-server sql-view sql-function


    【解决方案1】:

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

    观看次数

    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 类似。他们很可能不会被整体评估(甚至在某些情况下根本不会)or may be evaluated multiple times in others。多语句 TVF 将始终被评估并存储在返回表类型(基本上是一个表变量)中

    Occasionally the ability to parameterise inline TVFs directly can lead to a better execution plan than the equivalent parameterised query against a view.

    【讨论】:

    • tvf Is Updatable 是什么意思?
    • @RoyiNamir - 内联 TVF 可用于更新类似于视图的基表。
    • 您的意思是 TVF 可以从自身更新返回表吗?
    • @RoyiNamir - 示例CREATE TABLE T(C INT);EXEC('CREATE FUNCTION F () RETURNS TABLE AS RETURN (SELECT * FROM T)');INSERT INTO F() VALUES(1);SELECT * FROM T;
    • with check optionVIEW_METADATA 的其他一些区别
    【解决方案2】:

    在决定将我的SELECT 转换为VIEW 还是TVF 时,我通常有一个经验法则

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

    当然,这条规则纯粹是基于性能

    使用 TVF,我可以使用 CROSS APPLY,例如将其视为表格,但传递特定值,例如 主键

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

    性能更快!

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

    想一想。

    【讨论】:

      【解决方案3】:

      我发现,当在函数的返回表上指定 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
      

      【讨论】:

      • 浏览量也是如此。事实上,建立一个表会导致一个慢得多的函数。内联函数,即具有单个RETURNS 子句的函数不需要创建任何临时表,因此它的运行速度至少要快两倍。可能快很多,因为优化器可以将其查询包含在优化中
      猜你喜欢
      • 2018-04-21
      • 2021-03-28
      • 1970-01-01
      • 2014-09-01
      • 2013-05-29
      • 2011-08-24
      • 1970-01-01
      • 2011-01-04
      相关资源
      最近更新 更多