Python用cx_Oracle与pd.read_sql抽取60万条数据耗时过长求助
优化cx_Oracle + pandas.read_sql抽取大数据的性能
调大cx_Oracle的数组抓取大小
cx_Oracle默认的arraysize很小(通常是100),每次仅抓取100条数据,频繁的网络交互直接拖慢整体速度。建议根据本地内存情况调整到5000-20000之间:conn = cx_Oracle.connect("user/password@dsn") conn.arraysize = 10000 # 可按需调整 df = pd.read_sql(your_query, conn)用cx_Oracle原生cursor读取后转DataFrame
跳过pandas read_sql的中间封装,直接用cursor批量读取再构造DataFrame,能减少不少额外开销:conn = cx_Oracle.connect("user/password@dsn") conn.arraysize = 10000 cursor = conn.cursor() cursor.execute(your_query) # 提取列名 cols = [desc[0] for desc in cursor.description] # 批量抓取所有数据 data = cursor.fetchall() df = pd.DataFrame(data, columns=cols) cursor.close() conn.close()要是内存不够支撑一次性读取,就分块抓取拼接:
df_chunks = [] while True: chunk = cursor.fetchmany(10000) if not chunk: break df_chunks.append(pd.DataFrame(chunk, columns=cols)) df = pd.concat(df_chunks, ignore_index=True)避开SQLAlchemy连接(如果用了的话)
别用SQLAlchemy的引擎对象传给read_sql,直接传cx_Oracle的原生连接——SQLAlchemy的封装会增加不必要的性能损耗。处理大字段类型
查询里如果有CLOB、BLOB这类大字段,默认的读取方式极慢。要么直接去掉不需要的大字段,要么给连接加类型处理器优化读取:def handle_large_fields(cursor, name, default_type, size, precision, scale): if default_type == cx_Oracle.CLOB: return cursor.var(cx_Oracle.LONG_STRING, arraysize=cursor.arraysize) if default_type == cx_Oracle.BLOB: return cursor.var(cx_Oracle.LONG_BINARY, arraysize=cursor.arraysize) conn = cx_Oracle.connect("user/password@dsn") conn.outputtypehandler = handle_large_fields开启客户端结果缓存(针对重复查询场景)
如果你那6个同类查询有重复数据,可以开启客户端缓存,减少重复请求数据库的次数:conn = cx_Oracle.connect("user/password@dsn", events=True) cursor = conn.cursor() cursor.execute("ALTER SESSION SET RESULT_CACHE_MODE = FORCE")
内容的提问来源于stack exchange,提问作者SHRESTH SRIVASTAVA
相关产品推荐
相关产品推荐

