【问题标题】:pipelined function流水线功能
【发布时间】:2011-01-26 09:40:56
【问题描述】:

谁能提供一个如何在 oracle pl/sql 中使用并行表函数的例子。我们需要运行 15 年的海量查询并结合结果。

SELECT * 
  FROM Table(TableFunction(cursor(SELECT * FROM year_table))) 

...是我们真正想要的。最里面的 select 将给出所有年份,而 table 函数将每年执行大量查询并返回一个集合。我们遇到的问题是所有年份都被提供给一个表函数本身,我们宁愿每年都并行调用表函数。我们尝试了各种按哈希和范围进行的分区,但都没有帮助。

另外,我们可以从函数声明中删除关键字 PIPELINED 吗?因为我们没有执行任何转换,只需要结果集的聚合。

【问题讨论】:

  • 您能描述一下您想要实现的目标以及您认为需要管道功能的原因吗?目前,听起来您需要每年运行一个查询。
  • 即使我们每年运行一个查询,我们也需要在所有年份范围内并行执行。如果有比使用并行流水线更好的选择,请提出建议。

标签: sql oracle plsql parallel-processing performance


【解决方案1】:

有一篇很棒的文章here

还有其他方法(例如,“主”作业通过 YEAR_TABLE 进行游标并每年提交 DBMS_JOB 进行处理。每个“年作业”都会将其结果插入到表中。

一旦所有生成的作业都完成了,您只需从表格中提取结果。

PS。我怀疑并行流水线不会做你想要的。 我创建了一个只有三行具有特定值的大表。 然后我创建了一个并行流水线函数,它只是推出了正在执行的进程的 SID(见下文)和它处理的行数。 我有一个 SQL 可以挑选出这三行,并将其作为光标传递给函数。 大多数情况下,该功能推出了两个不同的 SID(这是 EXPLAIN PLAN 告诉我它选择的并行度)。有时它显示两个进程已执行,但所有三行都由其中一个进程处理。

因此,不会从游标中选择行并将其传递给并行从属设备进行处理,而是每个并行进程都将获得驱动表的一部分来处理。对于一个小表,它可能不会考虑并行,即使这样做,它也可能只是将前 50 行分配给第一个进程等。

CREATE OR REPLACE FUNCTION test_pp(p_source     IN SYS_REFCURSOR)
   RETURN TAB_CHAR_4000  PIPELINED
   PARALLEL_ENABLE (PARTITION p_source BY ANY)
IS
   v_num NUMBER;
BEGIN
   FETCH p_source INTO v_num;
   WHILE p_source%FOUND LOOP
            PIPE ROW(sys_context('USERENV','SID'));
            FETCH p_source INTO v_num;
   END LOOP;
     PIPE ROW(sys_context('USERENV','SID')||':'||p_source%ROWCOUNT);
   CLOSE p_source;
   RETURN;
END test_pp;
/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-04
    • 2022-07-14
    相关资源
    最近更新 更多