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

2 投票
1 回答
98 浏览
提问于 2025-04-12 10:20

我有一个非常大的 Pandas 数据框,大约有900万条记录和56列。我想把这些数据加载到一个MSSQL表中,使用的是 Dataframe.to_sql() 方法。但是一次性导入整个数据框经常会出现内存相关的错误。

为了应对这个问题,我开始把数据框分成每批10万条记录,逐批导入。这样做后,我不再遇到错误,但在导入到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
                    )

我对每批的时间进行了测量,发现速度有一个明显的拐点:

每20万条记录的时间

这些结果对于每批50k、100k和200k条记录基本相同。上传600万条记录大约需要40分钟,而接下来的300万条记录则需要另外2小时20分钟。

我认为这可能是因为MSSQL表的大小,或者是每次上传后某些东西被缓存或保存了。因此,我尝试将数据框推送到两个不同的表中。我还尝试在每次上传后对 SQLALchemy session 使用 expunge_all(),但都没有效果。

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

我已经没有其他想法来解释为什么这个过程会如此显著地变慢,非常希望能得到帮助。

更新

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

这样做后,每批的时间基本上反转了。所以看起来是数据本身在数据框的后面部分有所不同或更大,而不是连接过载或SQL表变得太大。

反向循环的批次时间

感谢所有尝试提供帮助的人,但看来我需要仔细检查数据,看看是什么导致了这个问题。

1 个回答

暂无回答

撰写回答