当使用游标迭代结果集时,将所有结果集加载到内存中

时间:2011-04-09 04:15:48

标签: sql-server oracle

如果结果集很大,使用游标会有内存效率吗?

2 个答案:

答案 0 :(得分:3)

通常,您应该尝试使用基于查询操作基于一组记录的“set”SQL语句,而不是使用游标并循环遍历数据。大多数DBA认为游标是邪恶的,因为它们占用了太多的内存,涉及阻止其他任务执行的锁,并且与经过深思熟虑的SQL语句相比效率也低得多(有时几个数量级)。

答案 1 :(得分:3)

从技术上讲,当您发出数据库查询时,游标始终。您可能正在考虑隐式和显式游标之间的区别吗?

就内存使用而言,重要的不是发出查询的方法,而是获取结果的方法 - 您可以选择批量获取结果(使用更多内存,但执行效果更好,效率更高)或单独获取每一行(使用较少的内存,但性能更差,效率更低)。

然而,权衡并非如此简单。如果你有大量的并发连接,所有同时运行的查询,效率可能比内存使用更重要 - 查询越早完成,数据库就越早可以提供其他请求。

如果我正在尝试优化我的PL / SQL以提高性能和内存使用率,我喜欢使用BULK COLLECT,在循环中使用LIMIT,例如:

DECLARE
  BATCHSIZE CONSTANT INTEGER := 1000;
  CURSOR mycursor IS SELECT ...;
  TYPE mytabletype IS TABLE OF mycursor%ROWTYPE INDEX BY PLS_INTEGER;
  myarray mytabletype;
BEGIN
  OPEN mycursor;
  LOOP
    FETCH mycursor INTO myarray LIMIT BATCHSIZE;
    EXIT WHEN myarray.COUNT = 0;
    FOR i IN 1..myarray.COUNT LOOP
      -- do the processing on myarray(i)
    END LOOP;
  END LOOP;
  CLOSE mycursor;
END;

上面的代码可以很容易地调整批量大小以最大化吞吐量,而不会在每个会话中使用太多内存。