首页 > 解决方案 > 使用 pandas 提高性能

问题描述

我正在从 SQL 服务器读取数据并.dat使用数据框写入文件。

记录总数为 31M+ 或 4.87GB 数据。读取和写入.dat文件需要 11.40 秒。当前的 VB 系统在 6 分钟内完成。

无论如何我可以提高我的脚本的性能吗?

def test_SQLPandas():
  conn = pyodbc.connect(sql, conn_str)
  df = pd.read_sql(sql, conn, chunksize=50000)
  i=1
  for data in df:
     data.to_csv('smaple.dat', sep='\t', mode='a')
     i+=1

标签: pythonsql-serverpandas

解决方案


我相信 sql server 是多线程的,可以同时响应多个请求。因此,我认为您应该像这样利用多处理:

import multiprocessing as mp
use_threads=mp.cpu_count()-1
batch_size=50000
conn = pyodbc.connect(sql, conn_str)
query='''your query...
          OFFSET {} ROWS 
FETCH NEXT {} ROWS ONLY;'''

tot_rows=pd.read_sql("select count(*) as tot_rows from your_table").iloc[0,0]

def read_sql(batch):
    df = pd.read_sql(query.format(batch*batch_size, (batch+1)*batch_size), conn)

with mp.Pool(use_threads) as pool:
    dfs=pool.map(read_sql, range(tot_rows//batch_size+1))

这个想法是在sql server中使用offset和fetch对查询进行批处理,并在您的机器上同时请求这些批处理的多个进程

然后,您可以将其连接到一张表中并编写 csv

pd.concat(dfs).to_csv("sample.csv")

或再次利用 mp

def to_csv(input):
    df, name=input
    df.to_csv(name)

with mp.Pool(use_threads) as pool:
        pool.map(to_csv, [(df, f'sample_{i}') for i,df in enumerate(dfs)])

推荐阅读