You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

向DuckDB表批量导入大量CSV时速度持续变慢的问题排查

从SQLite迁移至DuckDB时的CSV导入性能衰减问题

我正在从SQLite迁移到DuckDB,需要将10000个CSV文件(总计约2TB,近50亿行)导入到DuckDB表中,所有CSV的格式、结构、大小完全一致。最初导入单个CSV仅需2秒,但完成一半后每个CSV耗时增至15秒,且速度还在持续变慢。我在Windows环境下用Python操作,还发现必须断开并重新连接数据库才能释放内存,而SQLite没有这个问题。

我的代码如下:

# Process Each CSV File
for i, file in enumerate(csv_files, start=1):
    file_start_time = time.time()

    # Print progress message
    print(f"Processing file {i}/{total_files}: {file}")

    # Copy csv file to table
    query = f"COPY search_data FROM '{file}'"
    con.execute(query)

    # cleanup
    if i % batch_size == 0:
        con.close()  # Disconnect from DuckDB
        gc.collect()  # Force memory cleanup
        con = duckdb.connect(raw_duckdb_path)

解决方案建议

1. 配置内存限制与自动检查点

DuckDB默认会在内存中累积写操作,直到阈值才刷盘,这会导致内存占用持续上升拖慢性能。连接时可直接指定内存限制和自动检查点参数:

con = duckdb.connect(raw_duckdb_path, config={
    'memory_limit': '16GB',  # 根据机器总内存调整,建议设为总内存的70%
    'checkpoint_threshold': '2GB'  # 累积2GB写操作自动刷盘
})

2. 批量导入多文件,避免单文件循环

DuckDB的COPY支持直接读取多个文件,无需逐个循环处理,能大幅降低IO和连接开销:

# 按批次构造文件列表,比如每1000个文件一批
batch_size = 1000
for batch_start in range(0, len(csv_files), batch_size):
    batch_files = csv_files[batch_start:batch_start+batch_size]
    file_list = ",".join([f"'{f}'" for f in batch_files])
    query = f"COPY search_data FROM [{file_list}]"
    con.execute(query)

3. 关闭自动提交与实时统计更新

默认的自动提交和实时统计更新会在批量导入时产生额外开销,可临时关闭:

# 导入前关闭自动提交与统计更新
con.execute("PRAGMA auto_commit = false")
con.execute("PRAGMA disable_statistics = true")

# 执行所有导入操作后手动提交
con.execute("COMMIT")

# 导入完成后恢复统计更新
con.execute("PRAGMA disable_statistics = false")

4. 优化Windows环境IO性能

  • 将CSV文件存储在SSD上,避免使用HDD
  • 临时关闭Windows Defender实时扫描(导入完成后恢复)
  • 使用os.scandir()获取文件列表,比os.listdir()的IO效率更高

5. 取消频繁断开重连操作

当前的批量断开重连会增加连接初始化开销,改用内存限制和自动检查点配置后,无需断开连接即可控制内存占用。

内容的提问来源于stack exchange,提问作者Nik-D

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 15:27:06