【问题标题】:ORA-01652 error when fetching from cursorORA-01652 从游标获取时出错
【发布时间】:2019-04-08 08:43:43
【问题描述】:

我有一个存储过程,我使用游标循环访问临时表中的项目:

OPEN CURSOR_SCORE_ITEMS FOR SELECT 
        ID_X, ID_Y
    FROM
        SCORE_ITEMS
    GROUP BY 
        ID_X, ID_Y
    HAVING 
        SUM(SCORE) > 10;   
    LOOP
    FETCH CURSOR_SCORE_ITEMS BULK COLLECT INTO COMPARE_ITEMS LIMIT 100;

    ---loop over items and do stuff---

    END LOOP;
CLOSE CURSOR_SCORE_ITEMS;

对于“SCORE_ITEMS”表较小的情况,该过程运行良好,但对于大型表(数百万行),我收到错误

“ORA-01652: Temp-Segment kann nicht um 12800 in Tablespace TEMP_ALL erweitert werden"

(对不起,它是德语)。

请注意,SCORE_ITEMS 是一个临时表,它是在该过程的前面生成的。游标查询似乎超出了临时表空间的大小。

我已经阅读了一些涉及增加表空间大小的解决方案,但我对此数据库没有任何权限,所以我认为这是不可能的。是否有替代方法或我可能考虑的某种预处理来减少临时表空间中的开销?

【问题讨论】:

  • 你的临时表空间对于一个事务来说太小了,你应该在 x 行之后提交或者增加你的临时表空间的大小
  • 你在循环中做了什么?有没有机会将游标和循环的逻辑封装到单个 DML 语句中?或者,至少,将大部分计算移到打开光标中?另外,为什么要使用 ref 游标,而不是“普通”(即显式或隐式)游标?

标签: sql oracle plsql tablespace


【解决方案1】:

全局临时表被写入 TEMPORARY 表空间(即不是堆表的常用表空间)。你有单独的 GTT 临时表空间吗?我怀疑不是。大多数地方都没有。

所以(假设 ),当 SCORE_ITEMS 有数百万行时,您已经吃掉了一大块 TEMP。然后,您的查询以一个足以溢出到 TEMP 中的聚合开始 - 因为 GROUP BY 需要排序。

你已经排除了明显的解决方案:

增加表空间的大小,但我对此数据库没有任何权限,所以我认为这是不可能的。

我不知道这是否也排除了与您的 DBA 交谈并查看他们是否会增加分配给 TEMP 的空间,或者更好地为全局临时表创建一个新表空间的激进想法。

要考虑的另一件事是您是否真的需要 TEMP_SCORE。当人们可以编写更高效的 SELECT 时,填充 GTT 并不罕见。 GTT 中有很多开销——所有到磁盘的 I/O,更不用说争用共享 TEMP 表空间了。这绝对是一个值得考虑的选择。

【讨论】:

  • 谢谢,这很有帮助。因此,如果 SCORE_ITEMS 表是永久表而不是临时表,这是否意味着它不会被分配给 TEMP,这可能会为 GROUP BY 聚合释放足够的空间?那将是另一种可能性。
  • 您仍然会有写入和读取磁盘的开销,这在处理 “几百万行” 时显然更大。另外,您需要明确处理家务(清理)。最后,如果您可能有多个用户在任何给定时间运行此进程,则您需要处理会话隔离。
  • 对于未来的任何参考 - 让我们明确说明害怕 DBA 永远不是正确的答案!如果使用临时表对这个问题有意义并且避免了管家的麻烦——不要搞砸整个应用程序“因为 DBA 是一个我们无法交谈的圣人”!。永远不要因为政治而搞砸代码!
猜你喜欢
  • 1970-01-01
  • 2012-06-21
  • 1970-01-01
  • 1970-01-01
  • 2013-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多