流水线功能

时间:2010-03-11 14:14:07

标签: sql oracle plsql parallel-processing performance

有人可以提供一个如何在oracle pl / sql中使用并行表函数的示例。我们需要运行15年的大量查询并将结果结合起来。

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

......是我们想要的。最里面的选择将给出所有年份,并且表函数将每年运行并运行大量查询并返回集合。我们遇到的问题是,所有年份都被馈送到一个表函数本身,我们宁愿更喜欢并行调用表函数。我们通过哈希和范围尝试了所有类型的分区,但没有帮助。

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

1 个答案:

答案 0 :(得分:2)

有一个很好的写作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;
/