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

如何高效将磁盘DuckDB实例加载至内存实例且不修改源数据?

问题描述

我正在开展一个项目,第一阶段会拉取原始数据并通过DuckDB完成一系列处理,最终得到若干供下游DuckDB组件调用的表。需求如下:

  • 第一阶段的输出数据需持久化存储在磁盘上,且不被下游组件修改
  • 下游组件需要能够创建视图和临时表
  • 数据量较小足以存入内存,无需下游组件进行磁盘操作

我原本期望有类似如下的便捷解决方案:

conn = duckdb.connect("\:memory\:")
conn.load_from_disk(path_to_on_disk)

但目前DuckDB并未提供这类方法。我尝试过从磁盘连接读取每张表,转换为Pandas DataFrame后再加载到内存连接中,但该方法耗时极长。

以下是这种低效方法的示例:

def load_disk_duck_to_mem_duck(path: pathlib.Path) -> duckdb.DuckDBPyConnection:
    """Slow and ugly!"""
    source_db = duckdb.connect((path / "duck.db").as_posix())
    in_memory_db = duckdb.connect("\:memory\:")

    tables = source_db.execute("SHOW TABLES").fetchall()

    # 复制每张表从磁盘到内存
    for table in tables:
        table_name = table[0]
        temp_df = source_db.table(table_name).df()
        # 从磁盘加载表并在内存数据库中创建副本
        in_memory_db.from_df(temp_df).create(table_name)
    return in_memory_db
可行高效方案

方案1:通过ATTACH直接在内存连接中复制磁盘表

绕过Pandas的序列化/反序列化步骤,直接在DuckDB内部完成表复制,性能大幅提升:

import duckdb
from pathlib import Path

def load_disk_to_memory(path: Path) -> duckdb.DuckDBPyConnection:
    in_memory_conn = duckdb.connect(":memory:")
    # 挂载磁盘上的DuckDB数据库
    in_memory_conn.execute(f"ATTACH '{(path / 'duck.db').as_posix()}' AS disk_db")
    
    # 获取磁盘库中的所有表
    tables = in_memory_conn.execute("SHOW TABLES FROM disk_db").fetchall()
    
    # 复制每张表到内存库
    for table in tables:
        table_name = table[0]
        in_memory_conn.execute(f"CREATE TABLE {table_name} AS SELECT * FROM disk_db.{table_name}")
    
    # 卸载磁盘库,避免下游误修改
    in_memory_conn.execute("DETACH disk_db")
    return in_memory_conn

方案2:使用DUMP和LOAD命令迁移完整数据库对象

如果需要迁移包括表、视图在内的所有数据库对象,可导出磁盘库的SQL脚本后在内存库执行:

import duckdb
from pathlib import Path

def load_disk_to_memory(path: Path) -> duckdb.DuckDBPyConnection:
    disk_conn = duckdb.connect((path / 'duck.db').as_posix())
    # 导出所有表结构和数据为SQL语句
    dump_sql = disk_conn.execute("DUMP").fetchall()
    
    in_memory_conn = duckdb.connect(":memory:")
    # 执行SQL脚本在内存中重建数据库
    for stmt in dump_sql:
        in_memory_conn.execute(stmt[0])
    
    disk_conn.close()
    return in_memory_conn

方案3:只读挂载磁盘数据库(无需复制数据)

若不需要将数据完全加载到内存,仅需下游只读访问磁盘数据并允许创建内存级视图/临时表,可直接以只读模式连接磁盘库:

import duckdb
from pathlib import Path

def get_readonly_conn_with_temp_access(path: Path) -> duckdb.DuckDBPyConnection:
    # 以只读模式连接磁盘数据库,确保原始数据不被修改
    conn = duckdb.connect((path / 'duck.db').as_posix(), read_only=True)
    # 下游可创建临时表和视图,这些对象仅存在于当前连接的内存中,不会写入磁盘
    return conn

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 21:54:54