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

DuckDB参数调优咨询:内存配置与磁盘溢写疑问

问题背景

我有近800GB由维基百科转储解析得到的ndjson文件,需要按"url"分组、选取"dateModified"最新的"html"来去除重复HTML。针对16GB数据子集,我运行了以下代码:

import duckdb
from pathlib import Path

inDir   = r"E:\Personal Projects\tmp\result"
outDir  = r"C:\Users\Akira\Documents\enwiktionary.ndjson"
inDir   = Path(inDir)
outDir  = Path(outDir)

con = duckdb.connect()

con.execute("SET threads=5")
con.execute("SET memory_limit='12.5GB'")
con.execute("SET preserve_insertion_order=false")


result = con.sql(f"""
    COPY(
        SELECT
        arg_max(html, dateModified) as html
        FROM read_ndjson('{inDir / "*enwiktionary*.ndjson"}')
        GROUP BY url
        )
    TO "{outDir}"
""")

运行后出现如下错误:

---------------------------------------------------------------------------
OutOfMemoryException                      Traceback (most recent call last)
Cell In[5], line 16
     12 con.execute("SET memory_limit='12.5GB'")
     13 con.execute("SET preserve_insertion_order=false")
---> 16 result = con.sql(f"""
     17     COPY(
     18         SELECT
     19         arg_max(html, dateModified) as html
     20         FROM read_ndjson('{inDir / "*enwiktionary*.ndjson"}')
     21         GROUP BY url
     22         )
     23     TO "{outDir}"
     24 """)

OutOfMemoryException: Out of Memory Error: failed to allocate data of size 16.0 MiB (11.6 GiB/11.6 GiB used)

Possible solutions:
* Reducing the number of threads (SET threads=X)
* Disabling insertion-order preservation (SET preserve_insertion_order=false)
* Increasing the memory limit (SET memory_limit='...GB')

See also https://duckdb.org/docs/stable/guides/performance/how_to_tune_workloads

将"memory_limit"设为'13GB'时代码可正常运行。我的笔记本配备32GB内存、8核CPU(16线程),阅读官方内存管理文档后仍有以下疑问:

  1. DuckDB中哪些计算必须使用内存,无法溢写到磁盘?
  2. 针对当前数据集,如何调优memory_limit参数?
解答

1. DuckDB中必须在内存执行的计算

  • 哈希聚合构建阶段:执行GROUP BY时,DuckDB会先构建哈希表分组数据,这个哈希表的核心结构必须留在内存,无法直接溢写到磁盘。如果分组基数过大,内存不足以容纳哈希表,就会触发OOM。
  • 特定窗口函数计算:依赖全局排序或滑动窗口全量数据的窗口函数,部分中间结果无法溢出到磁盘,必须在内存中完成计算。
  • 小数据量临时操作:极小数据集或临时计算会直接在内存处理,不会触发磁盘溢出逻辑——磁盘IO开销远大于内存处理,没必要溢出。
  • 事务核心状态维护:事务的元数据、锁状态等核心信息必须在内存中维护,只有事务提交/回滚时才会持久化到磁盘。

2. 当前数据集的memory_limit调优建议

  • 基准阈值参考:从16GB子集的测试来看,13GB是刚好能运行的阈值。考虑到800GB全量数据的分组基数远大于子集,建议先将memory_limit设为20GB左右(预留12GB给系统和其他进程)。
  • 动态调整上限:如果全量运行仍OOM,可逐步增加内存限制,但不要超过总物理内存的80%(你的32GB内存,最高设为25GB左右),避免系统因内存耗尽卡顿或崩溃。
  • 配合其他参数优化:
    • 降低线程数到6-8:你的CPU是8核16线程,线程数设为核心数的1倍即可,过多线程会加剧内存竞争。
    • 指定临时目录:开启temp_directory参数,让DuckDB将可溢出的中间数据写到磁盘,减轻内存压力:
      SET temp_directory='D:/duckdb_temp';
      
    • 分批次处理全量数据:按url的哈希值拆分源文件,分批处理后合并结果,进一步降低单批次内存占用。

内容的提问来源于stack exchange,提问作者Akira

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.11 21:43:12