Python封装多条SQL语句优化性能:BEGIN...END实战与异常处理

栗子
栗子
发布时间:2026-10-14 | 2人浏览过
原创

本文介绍如何利用Python将多条SQL语句封装在BEGIN...END块中一次性提交,以减少数据库连接与网络传输开销,显著降低模型运行耗时。针对Oracle数据库唯一约束冲突(ORA-00001)问题,提供了基于字典去重并保留高权重因子的解决方案。同时补充了PostgreSQL中使用%s占位符时必须添加引号的注意事项,旨在提供高效且稳定的数据库交互方案。

Python封装多条SQL语句优化性能:BEGIN END实战

在Python中通过BEGIN...END块封装并执行多条SQL语句。

出于业务需求,需优化模型运行时间。由于每次单独执行SQL语句都需要建立连接、查询并获取数据,耗时过长,因此考虑将多条SQL语句合并提交运行,以节省大量时间。原本耗时1.6至2.5秒的SQL语句,经此方法修改后,耗时降至0.3至0.6秒,性能提升显著。

另一种思路是使用Python ORM框架,理论上可能更快,耗时几乎可忽略。但这仅为猜想,若仅为优化一个模型而引入整个框架,代码改动较大,投入产出比未必理想。未来若有时间,可尝试验证该方案。

本次优化未改动基本代码逻辑,主要利用BEGIN...END进行SQL整合。

公司使用Oracle数据库,此前未接触过,但感觉与MySQL基本类似。若使用MySQL,该方法同样适用。

sql_str = ‘begin\n' sql_str += ‘这里是需要执行的SQL语句' sql_str += ‘\ncommit;end;'

中间包含多少条SQL语句无关紧要。观察运行时间发现,一千行SQL的执行耗时几乎等同于其中耗时最长的那一条。至于异步执行或其他机制尚不清楚,核心优势在于仅建立一次连接,省去了网络传输数据和请求数据库的过程。

命令行执行BEGIN END的解决方案

网上许多关于BEGIN...END的示例仅在可视化工具中有效,无法在命令行(command)中直接执行,这意味着代码封装可能无效。幸而坚持研究找到了解决办法。

在END后提交即可解决问题。若在命令行中运行一直未结束,可添加一个斜杠(/)即可。

本次内容至此结束,以下补充一些题外话。

处理唯一约束冲突与因子重要度去重

分享一个遇到的问题:SQL封装后,涉及的表结构混乱,约束繁多且逻辑不严谨。由于模型正在运行且不允许修改底层规则,只能按现有规则处理。

遇到ORA-00001错误,即违反唯一约束条件。原因是模型输入导致处理结果可能与数据库中已存在的数据重复(即上述sql_str中出现了两次相同的INSERT语句)。解决此问题很简单,只需添加SET判断即可。但随之出现一个新Bug:该脚本计算因子重要度,预测结果每次可能不同,某些数据值较小可能被当作0处理。因此,需要在相同数据情况下插入重要度较高的因子(无需额外操作)。简单的SET无法解决此问题,但使用字典即可轻松应对。


 importance_map = {}
 实现创建好字典
 if feature in importance_map:
        if importance_map[feature] < importance:
          sql_str +=‘***************‘'' 这里就是insert语句了
        else:
          continue
      else:
        importance_map[feature] = importance

内存管理与Pandas使用反思

其实该问题并无难点,但解决过程中引发了诸多思考。

数据处理本可使用Pandas,但Pandas是对所有数据进行操作,而此处仅需对重复数据进行SET操作。此外,Pandas内存消耗极大,前几日进行特征工程时内存溢出。表数据处理完毕后,内存并未释放,这涉及Python的垃圾回收机制,具体用法尚需研究。gc主要针对循环引用进行垃圾回收和内存释放,但Pandas并非循环引用,而是存储在缓冲区中,位置固定,导致内存无法释放,令人困扰。

模型在服务器上运行,务必追求快速且节省内存,否则占用过多内存会影响其他项目运行。因此采用上述方法。

很少撰写博客,主要为了记录问题,以便日后应对。若能帮助正在修复Bug的你,亦感欣慰。若有表述不清或错误之处,欢迎留言指正。

PostgreSQL使用%s占位符的注意事项

补充知识:PostgreSQL SQL中使用%s时务必添加引号,即‘%s',否则报错。

PostgreSQL SQL中使用%s时务必添加引号,即‘%s',否则报错。

if name == ‘main':


t="TDD-LTE_MRO"
sql="select * from lastftp where enbid = %d and keytype = %s"%(110001,t)

print(selectOperate(sql))

结果:


Traceback (most recent call last):
File “/home/eyann/mypython/t1/pgSQLoperate.py”, line 84, in
print(selectOperate(sql))
File “/home/eyann/mypython/t1/pgSQLoperate.py”, line 45, in selectOperate
cursor.execute(sql)
psycopg2.ProgrammingError: column “tdd” does not exist
LINE 1: …* from lastftp where enbid = 110001 and keytype = TDD-LTE_MR…
^

if name == ‘main':


t="TDD-LTE_MRO"
sql="select * from lastftp where enbid = %d and keytype = '%s'"%(110001,t)

print(selectOperate(sql))

结果:

[(‘test3', ‘TDD-LTE_MRO', ‘0114123000', ‘0012', 110001)] [Finished in 0.1s]

以上关于Python实现一次性封装多条SQL语句(BEGIN...END)的内容即为分享的全部,希望能提供参考,也希望大家多多支持本站。

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表