oracledb.exceptions.DatabaseError: DPI-1001: out of memory 错误处理

从cx_oracle 7.21 切换到 cx_oracle 8.x 或者 oracledb(测试时为1.2.1最新版)后,在用executemany进行数据导入数据库时,会遇到内存不足错误:

oracledb.exceptions.DatabaseError: DPI-1001: out of memory

报错轨迹看,是来自变量绑定时出现的。通过测试,发现可以降低没批次的行数来解决,就是每次导入行数少,多循环次数导入可以。为什么原来能一次导入而现在不行了呢,查找新的版本的doc,对数据进行测试发现,可以通过setinputsizes 来解决。

通过对数据进一步研究发现,主要是因为不设置时,会有一些大的字段默认分配4000字符(4000*4=16000bytes),字段多的时候,就导致占用较多报错了(我用到的导入的电子表格有100列)。测试时,先看了doc的批量导入优化的内容,采用了对导入的字符串字段预先求出最大长度,然后设置到setinputsizes里,比如各个字段最大长度分别是 5,20,40,10,50...,那么可以设置 setinputsizes(5,20,40,10,50,....),这样不会出现超长占用内存的情况,可以一次导入上万行了。 具体探测字段内存和长度用到的语句:

    for var in cursor.bindvars:
        print(var.buffer_size,var.size)

以上方式,每次都要计算最大长度,可能略显啰嗦,也可以用简单的方式:

cursor.setinputsizes(1,1,1,1,1)
#或者
cursor.setinputsizes(*(1 for i in range(cols)) ) #cols为列数 

这样设置,运行就可达到原来的效果,不知是新版本估计忽略了基础设置,还是bug,也还是想以此来提醒编程时注意相关的设置呢。这样设置按照doc说明,执行中会在发现新的较长的字段时,重新分配内存并有数据重新copy影响性能的情况。

如果是进行库表对库表的传输,可以使用查询源库表的结构直接设置:

cursor.setinputsizes(*(t[1] for t in src_cursor.description))

以上是个人在使用升级时遇到的out of memory的解决情况,如果你也遇到这个问题,希望能给到帮助。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值