我们每天都在运行一项任务,将查询结果转储到 CSV 文件中——作为sqlplus
运行查询的标准输出。
记录数为数百万(不要问),这项工作需要两个多小时。
在尝试改进时间安排时,我编写了一个 C 程序(使用 Oracle 的ofetch()
调用),但性能没有改变……在客户端增加会话数据单元 (SDU) 大小(到 1GB!)——不确定,服务器会夹住它)没有帮助。
然后我做了一些更多的研究并发现,ofen()
如果用于一次捕获多行,可以显着提高性能 - 并更改了我的 C 程序来使用它。
一次获取 4K 行,时间缩短到 21 分钟 - 减少了 10 倍 - 令人欣喜若狂。
在我们在生产服务器上安装我的新可执行文件之前,也许,股票sqlplus
也可以执行相同的多行获取——如果提供了正确的命令行选项?
它可以?虽然我们使用的是 Oracle-11,但如果客户端版本 12 中提供了此功能,我们可以升级客户端......
SET ARRAYSIZE 的默认值为 15
"设置 SQL*Plus 一次从数据库中获取的行数。
有效值为 1 到 5000。较大的值会提高获取许多行的查询和子查询的效率,但需要更多内存。超过大约 100 的值几乎不会提供额外的性能。除了提高效率之外,ARRAYSIZE 对 SQL*Plus 操作的结果没有影响。”
https://docs.oracle.com/en/database/oracle/oracle-database/12.2/sqpug/SET-system-variable-summary.html#GUID-773AEA4E-060E-4C1E-B1A0-52F7DE084AE8
可以在 sqlnet.ora(更改 DEFAULT_SDU_SIZE )或连接字符串中进行其他调整(包括 SDU)。这可以在 tnsnames.ora 中定义,但您也可以将其作为 versbose 连接字符串的一部分,例如
为 usr、pwd、svr 和 svc 输入适当的值 https://docs.oracle.com/cd/E18283_01/network.112/e10836/performance.htm
我认为加里的建议是合理的。您也可以尝试使用 utl_file 或直接将数据写入文件的 Perl 脚本进行测试。我会犹豫编写 C 程序,因为这需要更高水平的专业知识来维护。