大DataFrame操作优化:Oracle表抽取后Pandas合并超50万行数据效率低求解
性能问题原因
- 循环内重复初始化高开销操作:每次遍历BU时都会重复读取本地SQL文件、新建Oracle数据库连接,连接建立和文件IO的开销被循环放大,BU数量越多浪费的时间越多
- 数据读取逻辑冗余:手动分块读取SQL结果再拼接成DataFrame的操作完全多余,反而增加了内存拷贝和循环开销;没有调整cx_Oracle的默认预取参数,数据库查询的网络IO效率很低
- 关联操作性能差:多字段关联时如果关联键是未优化的
object字符串类型,匹配速度会非常慢;默认pd.merge会自动对关联键排序,不需要排序的场景下会额外浪费性能 - 冗余代码和无效操作:重复导入pandas包,声明了
dfs、dfs2等空DataFrame但从未使用,额外占用内存资源 - 代码逻辑错误:你定义的BU列表变量为
bu_list_MERE、bu_list_GARE等,但是bu_list_map中映射的是不存在的bu_list_APPLE、bu_list_PEACH变量,运行会直接抛出NameError
优化方案
- 调整操作的执行层级:把SQL文件读取、数据库连接创建的逻辑移到BU循环外,整个任务周期只执行一次:
# 循环外提前读SQL文件 query1_template = open('gla_va_parametre - VAR.sql',"r").read() query2_template = open('cle-gla_tva - VAR.sql',"r").read() # 循环外提前创建连接 connection_EPOST = cx_Oracle.connect(user=config.user_EPOST, password=config.password_EPOST, dsn=config.host_EPOST) connection_FPOST = cx_Oracle.connect(user=config.user_FPOST, password=config.password_FPOST, dsn=config.host_FPOST) # 调整cx_Oracle预取参数提升查询效率 connection_EPOST.cursor().arraysize = 50000 connection_FPOST.cursor().arraysize = 50000
- 简化数据读取逻辑:删掉手动分块读取的逻辑,直接用
pd.read_sql一次性拉取全量数据,性能远高于手动分块拼接 - 优化merge性能:关联前统一关联键的数据类型,关闭不需要的排序操作:
jointure = pd.merge(dfs,dfs2,how='left', left_on=['Code_BU_GL','Code_division','Code_ecriture','Date_comptable','Code_ligne_ecriture','UNPOST_SEQ'], right_on=['BUSINESS_UNIT','OPERATING_UNIT','JOURNAL_ID','JOURNAL_DATE','JOURNAL_LINE','UNPOST_SEQ'], sort=False # 关闭排序大幅提升速度 ).drop(columns= ['BUSINESS_UNIT','OPERATING_UNIT','JOURNAL_ID','JOURNAL_DATE','JOURNAL_LINE'])
- 优化CSV写入速度:写入时指定更快的引擎,开启分块写入:
jointure.to_csv(f'out/gla_va_{year}{month}_{societe_var}_{bu}_{date.today().strftime("%Y%m%d")}.csv', index=False, sep='|', engine='pyarrow', # 需提前安装pyarrow包,速度提升2-5倍 chunksize=100000)
- 清理冗余代码:删掉重复的
import pandas、无用的空变量声明,用f-string代替字符串加号拼接,提升可读性和执行效率 - 修复变量名错误:把
bu_list_map里的变量名替换为你实际定义的BU列表变量名
内容的提问来源于stack exchange,提问作者Kair0
相关产品推荐
相关产品推荐

