表函数和流水线函数的区别?

Posted

技术标签:

【中文标题】表函数和流水线函数的区别?【英文标题】:Difference between Table Function and Pipelined Function? 【发布时间】:2014-01-16 19:44:14 【问题描述】:
CREATE OR REPLACE TYPE ty_1 AS OBJECT ( fn VARCHAR2(100),
                                        sl NUMBER,
                                        hd DATE );
CREATE OR REPLACE TYPE ty_1_table AS TABLE OF ty_1;

CREATE OR REPLACE FUNCTION FN_RET_COL
  RETURN ty_1_table
AS
  c ty_1_table := TY_1_TABLE();
  BEGIN
    c.extend;
    C(1) := TY_1('A', 1, '10-JUN-2013');
    c.extend;
    C(2) := TY_1('B', 2, '11-JUN-2013');
    c.extend;
    C(3) := TY_1('C', 3, '12-JUN-2013');

    RETURN c;
  END;

CREATE OR REPLACE FUNCTION FN_RET_PIPE RETURN ty_1_table PIPELINED IS
  BEGIN
    PIPE ROW (TY_1('A', 1, '10-JUN-2013'));
    PIPE ROW (TY_1('B', 2, '11-JUN-2013'));
    PIPE ROW (TY_1('C', 3, '12-JUN-2013'));
  END;

SELECT * FROM TABLE (fn_ret_col);

SELECT * FROM TABLE (fn_ret_pipe);

第一个FN_RET_COL 是常规表函数,第二个FN_RET_PIPE 是流水线函数。 我在一本像 常规表函数要求集合在返回之前完全填充,其中PIPELINED FUNCTION 使用PIPE ROW 调用将行在创建后立即从函数中推出,而不是建立表集合。节省内存并允许在生成所有行之前开始后续处理。 我的疑问是:PIPELINED Function 如何节省内存? 如果我没记错的话,它将所有行都管道化并将它们存储在内存区域中,然后在控制台中打印所有行。还是像这样,只要在控制台中通过管道传输新记录就直接逐行打印而不将其存储在任何地方?

CREATE OR REPLACE FUNCTION FN_RET_COL RETURN TY_1_TABLE
 PIPELINED IS
 BEGIN   
    PIPE ROW(TY_1('A',1,'10-JUN-2013'));
    DBMS_LOCK.sleep(seconds => 10);
    PIPE ROW(TY_1('B',2,'11-JUN-2013'));
    DBMS_LOCK.sleep(seconds => 10);
    PIPE ROW(TY_1('C',3,'12-JUN-2013'));
 END;

如果我的第二种情况是正确的,那么上面的代码是如何工作的?

【问题讨论】:

【参考方案1】:

Pipelined 函数,一个非常经典的例子是你在SQL*Plus 中执行SELECT * FROM table name。发生的情况是,Oracle 从表中流式传输数据..

喜欢在 youtube 上观看视频。

请注意“流式传输”这个词。在我们的函数中,我们定义了流式传输的行数。每个流式传输行都可以立即供调用者使用。 Pipelining 通俗地说,不要让我等你完成,把你有的给我,同时继续处理和更新我。

在您的最后一个过程中,在对每一行进行管道传输之后,您启动了对 10ssleep 调用,因此记录每 10 秒流式传输到调用者。

而且,一个普通的表函数会一直等待,直到所有处理工作完成,然后它会返回对结果集游标的引用。

他们声称可以节省内存的流水线函数通过flushing 立即获取内容,因此所使用的缓冲区始终是最小的,而往返次数越来越多。

【讨论】:

创建或替换函数 FN_RET_COL RETURN TY_1_TABLE 流水线开始为 i in (SELECT FIRST_NAME,SALARY,HIRE_DATE FROM EMPLOYEES WHERE ROWNUM 1);结束循环;结尾;从表中选择 A.FN,LOCALTIMESTAMP(FN_RET_COL) A;在这里,我得到的时间和表函数一样。为什么?实际上它应该在传输一行后立即返回。

以上是关于表函数和流水线函数的区别?的主要内容,如果未能解决你的问题,请参考以下文章

如何在“流水线表函数”、视图和显式游标之间进行选择

Oracle 流水线表函数并将结果插入到 Oracle 表中

如何使用光标创建流水线函数并返回表?

使用流水线函数从多表join获取结果集。

创建函数 - 流水线 DB2

SQL Developer 中流水线函数的性能很差