如何优化Oracle PL/SQL中的Bulk Collect批量提取性能?

小芳大大_3966

小芳大大_3966

2026-06-25

955人浏览

原创

必须显式写limit,因为bulk collect默认不限行数,会一次性将全表数据加载至pga内存,极易触发ora-04030导致oom崩溃;典型安全值为100–1000行/批,含lob时应压至100以下。

不加 limit 的 bulk collect 很容易把 pga 帐户刷爆,不是慢,是直接崩——ora-04030 出现前往往没任何预警。

为什么必须显式写 LIMIT,不能靠默认行为

BULK COLLECT 默认不限行数,它会把整个结果集一次性加载进 PGA 内存。查一张 50 万行、每行平均 1.2KB 的表,就是约 600MB PGA 占用,远超多数实例的单会话 PGA 限制(通常 200–500MB)。这不是“性能差”,是资源耗尽导致会话被杀。

  • LIMIT 必须写在 FETCH 语句末尾,比如 FETCH c_emp BULK COLLECT INTO l_tab LIMIT 1000;它不能放在 SELECT 或 OPEN 里
  • 别信“我这台服务器内存大”,RAC 环境下 PGA 是共享的,一个游标吃光内存会影响其他所有会话
  • 典型安全值:100–1000 行/批;含 CLOB 或 BLOB 字段时,建议压到 100 以下

集合类型选错会导致 FORALL 失效或报 ORA-06502

不是所有集合都能传给 FORALL。VARRAY 长度固定,容易溢出;INDEX BY VARCHAR2 下标不连续,FORALL i IN 1..v_tab.COUNT 会跳过空位漏数据;而纯 INDEX BY PLS_INTEGER 在某些 DML 场景下不支持绑定。

  • 优先声明为 TYPE t_tab IS TABLE OF your_table%ROWTYPE(嵌套表),这是最通用稳妥的选择
  • 如果只更新部分字段,别用 %ROWTYPE,改用显式字段集合:TYPE t_ids IS TABLE OF employees.employee_id%TYPE,再 SELECT emp_id BULK COLLECT INTO v_ids FROM ...
  • BULK COLLECT INTO 的目标变量必须是集合类型,不能是标量或记录变量;类型和 SELECT 字段顺序、精度必须严格匹配

怎么判断游标取完了?别信 %NOTFOUND

%NOTFOUND 在 BULK COLLECT 后不可靠。比如最后一批只取到 1 行,%NOTFOUND 仍是 FALSE;只有再 FETCH 一次才会变 TRUE——这会导致多一次空 fetch,浪费 IO 且可能触发异常。

QuantOracle
QuantOracle

63个确定性量化金融计算器 + 10个通过MCP的复合工作流。期权定价、Greeks、奇异衍生品、风险指标、投资组合优化……

下载
  • 正确退出条件是 EXIT WHEN l_tab.COUNT = 0,每次 FETCH 后立刻检查集合长度
  • 如果集合为空,l_tab.COUNT 返回 0,不会报错,可安全用于判断
  • 别在 FORALL 前清空集合用 l_tab := t_tab(),要用 l_tab.DELETE,否则旧数据残留导致逻辑错误

FORALL 更新时怎么知道哪几条没生效

FORALL 默认只要一条失败,整批回滚。加 SAVE EXCEPTIONS 只是“延迟报错”,不查 SQL%BULK_EXCEPTIONS 就等于没捕获。

  • 必须紧跟 FORALL 后用 EXCEPTION WHEN OTHERS THEN 包裹,并检查 SQL%BULK_EXCEPTIONS.COUNT > 0
  • 遍历时用 SQL%BULK_EXCEPTIONS(i).ERROR_INDEX 对应回原始集合下标,不是数组索引
  • 拼错误信息时记得加负号:SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE),漏负号返回空字符串
  • 别忽略 SQL%BULK_ROWCOUNT:某条 UPDATE 的 WHERE 条件不匹配时,SQL%BULK_ROWCOUNT(i) 返回 0,但不会报错

最常被忽略的是分页粒度与单行体积的耦合关系——LIMIT 设成 1000 没问题,但若某列是 CLOB,实际内存占用可能翻 10 倍。上线前必须用真实数据跑一次 V$PGA_TARGET_ADVICE 查峰值。

相关文章

数码产品性能查询
数码产品性能查询

该软件包括了市面上所有手机CPU,手机跑分情况,电脑CPU,电脑产品信息等等,方便需要大家查阅数码产品最新情况,了解产品特性,能够进行对比选择最具性价比的商品。

下载

相关标签:

oracle

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
oracle清空表数据
oracle清空表数据

当表中的数据不需要时,则应该删除该数据并释放所占用的空间。本专题为大家提供oracle清空表数据的相关文章,帮助大家解决该问题。

2023.08.16

981

5

Oracle中declare的使用
Oracle中declare的使用

Oracle DECLARE语句是PL/SQL编程语言中用于声明变量、常量、游标或异常的关键字。它的主要作用是在程序中定义这些对象,以便在后续的代码中使用。DECLARE语句的语法简单明了,可以根据需要声明多个对象。通过使用这些声明的对象,可以进行各种操作,如计算、查询数据库、处理异常等 。

2023.09.15

2893

5

oracle怎么分页
oracle怎么分页

实现分页的步骤:1、使用ROWNUM进行分页查询;2、在执行查询之前进行设置分页参数;3、使用"COUNT(*)"函数来获取总行数,并使用"CEIL"函数来向上取整计算总页数;4、在外部查询中使用"WHERE"子句来筛选出特定的行号范围,以实现分页查询。想了解更多oracle怎么分页的文章,可以来阅读本专题先的文章。

2023.09.18

2890

5

Oracle查看表操作历史记录
Oracle查看表操作历史记录

查看操作历史记录的方法:1、使用Oracle内置的审计功能,可以记录数据库中发生的各种操作,包括登录、DDL语句、DML语句等;2、使用Oracle日志文件,其中包含了数据库中发生的各种操作,可以通过查看日志文件来获取操作历史记录;3、使用Oracle的Flashback功能,可以查看数据库在某个时间点的操作历史记录;4、使用第三方工具等。本专题还提供其他查看表操作的文章,大家可以免费阅读。

2023.09.19

1649

3

Oracle中RAC的用法
Oracle中RAC的用法

Oracle中RAC的用法:1、通过在多个服务器上运行数据库实例来提供高可用性;2、允许在需要时增加或减少节点数量;3、通过将工作负载分布到多个节点上来实现负载均衡;4、使用共享存储来实现多个节点之间的数据共享;5、允许多个节点同时处理数据库请求,从而实现并行处理;6、提供了透明故障切换功能;7、使用了一些技术来确保数据的一致性;8、提供了管理工具来简化RAC环境的管理和维护。本专题还提供RAC相关的其他文章,大家可以免费阅读。

2023.09.19

2273

7

oracle imp
oracle imp

imp是Oracle数据库中的一个命令行工具,用于将导出的数据和对象从一个数据库实例导入到另一个数据库实例。imp命令的一般语法为“imp username/password@connect_string file=file_name [options]”。

2023.09.19

3069

4

常用的数据库软件
常用的数据库软件

常用的数据库软件有MySQL、Oracle、SQL Server、PostgreSQL、MongoDB、Redis、Cassandra、Hadoop、Spark和Amazon DynamoDB。更多关于数据库软件的内容详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.02

4529

19

oracle通配符有哪些
oracle通配符有哪些

oracle通配符有“%”、“_”、“[]”和“[^]"。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.11.08

237

5

oracle四舍五入怎么操作
oracle四舍五入怎么操作

oracle四舍五入操作可以使用ROUND函数来实现,其语法为“ROUND(number, decimal_places)”,其中,number是要进行四舍五入的数值,decimal_places是指定的小数位数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.11.14

786

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程