【问题标题】:Replace iteration's fetch to BULK COLLECT将迭代的 fetch 替换为 BULK COLLECT
【发布时间】:2011-11-28 04:07:54
【问题描述】:

有一个对象类型,表由该对象组成。 所以我们开始:

create or replace type lpu.someobj_o as object
(      
  name VARCHAR2(75),     
  enroll_date DATE,
  id NUMBER(12)
)

CREATE OR REPLACE TYPE lpu."SOMEOBJ_T" IS TABLE OF someobj_o;

还有一个通用的 PL/SQL 函数ETL principle。这是一段代码功能:

  for some_cursor_rec in some_cursor(startTime, recordInterval) loop
  open some_cur2(some_cursor_rec.name, some_cursor_rec.id);
  fetch some_cur2 into some_cursor_rec2;
  if some_cur2%rowcount > 0 then
    loop
      pipe row (
        lpu.someobj_o(
        id => some_cursor_rec2.id, 
        name => some_cursor_rec2.name, 
        enroll_date => some_cursor_rec2.enroll_date
      )
      );
      fetch some_cur2 into some_cursor_rec2;
      exit when some_cur2%notfound;
    end loop;      
  end if;
  close some_cur2;
end loop;

好的,所以问题是性能很小。如何提高完成此功能的速度?我读过BULK COLLECT 应该会提高性能。但是我如何在我的情况下使用它?我尝试过BULK COLLECT,但它给了我错误,即集合类型错误。 提前致谢!真心希望得到您的帮助!

【问题讨论】:

  • FETCH 带有BULK COLLECT 子句的语句? download.oracle.com/docs/cd/E11882_01/appdev.112/e17126/…
  • 我对在流水线函数中使用bulk collect 的好处有点怀疑。即使您一次加载多行,您仍然只能一次将其中一个通过管道传输到输出。就此而言,除非函数中正在进行更多处理,否则我不得不质疑您为什么首先使用流水线函数。
  • 如果需要更好的性能,我可以拒绝流水线函数。你推荐给我吗?

标签: database oracle plsql cursor


【解决方案1】:

如果您关心性能,那么您应该开始考虑组合两个光标。

当前您正在执行 some_cursor 中的查询一次,并且您在游标 some_cur2 中执行查询的次数与第一个查询中选择的行数一样多。这很可能是您的性能瓶颈。

如果您将两个查询合并为一个查询并执行游标 for 循环(仅执行一次查询),那么您将自动一次批量获取 100 行,因此可能不会有真正的需要手动将其转换为批量获取。

问候,
抢。

【讨论】:

  • 我以前试过一个复杂的光标。而且我只用一个光标就可以降低性能。函数在大约 1 秒内完成执行。现在(有两个光标)我们还有大约 0.1 秒的时间。第一个游标将带来大约 5-15 条记录,秒游标为每个第一个游标的记录返回大约 40-50 条记录。请问有什么建议吗?
  • 我的建议是发布两个游标和你的一个游标,以及他们的计划,以便我们看看他们。您可以按照这篇文章中的建议进行操作:forums.oracle.com/forums/thread.jspa?messageID=1812597
【解决方案2】:

这是一个基本示例,如何将bulk collect into 与对象类型一起使用。

create or replace type someobj_o as object
(      
  name varchar2(75),     
  enroll_date date,
  id number(12)
);
/

create or replace type someobj_t is table of someobj_o;
/

create table someobj_table of someobj_o;

insert into someobj_table values(someobj_o('Joe', current_date, 100));
insert into someobj_table values(someobj_o('Jack', current_date, 101));
insert into someobj_table values(someobj_o('John', current_date, 102));

declare
  v_objs someobj_t;
begin
  select someobj_o(name, enroll_date, id)
    bulk collect into v_objs
    from someobj_table;

  dbms_output.put_line('number of objects in a collection = ' || v_objs.count);
end;
/

更新

同上,带光标:

declare
  type objcur_t is ref cursor;
  v_objcur objcur_t;
  v_objs someobj_t;
begin
  open v_objcur for
    select someobj_o(name, enroll_date, id)
    from someobj_table;

  fetch v_objcur bulk collect into v_objs;

  close v_objcur;

  dbms_output.put_line('number of objects in a collection = ' || v_objs.count);
end;
/

【讨论】:

  • 我在网上看到过类似的例子。但我确实需要用BULK COLLECT INTO 填充光标中的someobj_table。我怎样才能让它工作?
  • @kseen:当我将代码剪切并粘贴到 SQLPLUS 时,可以在我的 Oracle 11.2.0.1.0 上完美运行。您正在运行哪个 Oracle 版本?
猜你喜欢
  • 2015-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-12
  • 1970-01-01
相关资源
最近更新 更多