为什么 Dataframe.to_sql() 在达到一定数量的行后会变慢?

问题描述 投票:0回答:1

我有一个非常大的

Pandas
数据框,大约有900万条记录,56列,我正在尝试使用
Dataframe.to_sql()
将其加载到MSSQL表中。在一条语句中导入整个 Dataframe 通常会导致与内存相关的错误。

为了解决这个问题,我以 100K 行为一批循环遍历 Dataframe,并一次导入一批。这样我就不再遇到任何错误,但在大约 580 万条记录后,代码速度显着减慢。我正在使用的代码:

maxrow = df.shape[0]
stepsize = 100000
for i in range(0, maxrow, stepsize):
    batchstart = datetime.datetime.now()
        
    if i == 0:
        if_exists = 'replace'
            
    else:
        if_exists = 'append'
        
    df_import = df.iloc[i:i+stepsize]
        
    df_import.to_sql('tablename', 
                    engine,
                    schema='tmp',
                    if_exists=if_exists,
                    index=False,
                    dtype=dtypes
                    )

我已经对批次进行了计时,速度上有一个明显的断点: 对于 50k、100k 和 200k 行的批次,这些结果基本相同。上传 600 万条记录大约需要 40 分钟,上传接下来的 300 万条记录需要 2 小时 20 分钟。

我的想法是,这要么是由于 MSSQL 表的大小,要么是由于每次上传后缓存/保存的内容所致。因此,我尝试将数据框推送到两个不同的表。每次上传后,我还在

expunge_all()
上尝试过类似
SQLALchemy session
的操作。两者都没有效果。

在 500 万条记录后手动停止导入并使用新的引擎对象从 500 万条记录重新启动也没有帮助。

我完全不知道导致该过程如此急剧减慢的原因是什么,并且非常感谢您的帮助。

更新

作为最后的手段,我反转了循环,从最高索引开始上传部分数据帧,然后向下循环。

这基本上扭转了每批次的时间。所以看起来数据本身在数据帧中是不同/更大的。不是连接过载或 SQL 表变大。

感谢大家的帮助,但看来我需要查看数据来看看是什么原因造成的。

python sql-server pandas sqlalchemy
1个回答
0
投票

我找到了一个解决方案,对于其他希望加快缓慢(ing)

Dataframe.to_sql()
操作的人来说可能很有用,并且已经尝试过类似
chunksizes
之类的方法并设置
SQLALchemy
fast_executemany=True的连接
.

不确定是什么机制导致了这种性能变化,但它对我有用,而且我没有在其他地方看到它被提及。所以我希望它对其他人有帮助。

使用

DataFrame.sort_values()
对原始 Dataframe 进行排序已将所需时间减少了大约 2/3。

值在哪些列上排序似乎非常重要。当 Dataframe 按唯一的列排序并且行为类似于嵌套/聚集排序时,速度是最好的。按此列排序隐式按约 20 列排序。

它对地址进行排序,同时对街道、邮政编码、城市、地区等进行排序。这也意味着批次中的许多行共享行中的许多值。当 Dataframe 按与其他列没有连接的另一列排序时,它实际上会显着减慢

Dataframe.to_sql()
速度。

© www.soinside.com 2019 - 2024. All rights reserved.