DeepSeek总结的一个不含数据的 DuckDB 数据库

一个不含数据的 DuckDB 数据库

DuckDB 团队

2026-10-07 | 6 分钟

摘要:DuckDB 数据库文件不必包含任何数据。它可以只存储指向对象存储上 Parquet 文件的视图定义,因此几百千字节的文件就能像一个覆盖整个数据湖的共享目录一样运作。本文展示如何构建这样的文件、托管它,并以只读方式附加。

DuckDB 数据库文件不必包含任何数据。它可以只存储指向存储在其他地方的文件(例如对象存储上的 Parquet)的视图定义。无论它所描述的数据有多大,该文件都保持几百千字节,任何附加它的人都会看到一组已命名的关系,随时可以查询。

Nikolas Goebel 在《DuckDB 不需要数据》⁠ 中描述了这个想法,该文认为现代数据库已经将数据存储位置与读取方式分离,以至于大多数数据库不再需要保存自己的任何数据。从这个角度来看,DuckDB 成为数据云的浏览器,你通过 URL 而不是自己磁盘上的副本来访问数据集。

在这篇博客文章中,我们将这个想法变成一个小的、可共享的目录。

想法

DuckDB 表将其行存储在数据库文件内部。视图只存储查询的文本。当你读取视图时,DuckDB 运行该查询并返回当前结果。如果查询读取远程 Parquet 文件,数据就存在于对象存储中,而视图只保存如何读取它的指令。

完全由这类视图构成的数据库文件不包含自己的任何行。它是一个目录:一组已命名的、随时可查询的关系,建立在保持在其原始位置和格式的数据之上。你可以将该目录作为数据湖上的精选语义层发布,其中视图定义编码了消费者应使用的连接、过滤器和列名,而无需复制或移动底层数据。

构建视图目录

这些示例使用 DuckDB 的公开列车服务数据集,该数据集为荷兰铁路列车停靠的每一站记录一行。数据来自 Rijden de Treinen("列车在运行吗?")应用程序发布的开放数据集⁠,你可以直接从其 URL 读取。

首先,安装 httpfs 扩展,以便 DuckDB 可以通过网络读取。这只需运行一次。

sql 复制代码
INSTALL httpfs;

现在创建一个持久数据库文件,并在远程数据上定义一个视图。使用完全限定的位置、远程 URL 或绝对路径,以便视图无论客户端的工作目录如何都能解析。

sql 复制代码
ATTACH 'rail_catalog.duckdb' AS rail;
USE rail;

CREATE VIEW services AS
    SELECT *
    FROM 'https://blobs.duckdb.org/train_services.parquet';

该目录现在公开一个 services 关系,每当查询它时都会从远程文件读取。

sql 复制代码
SELECT departure_time, station_name, type
FROM rail.services
LIMIT 3;
departure_time station_name type
2023-05-15 00:00:00 Rotterdam Centraal Intercity
2023-05-15 00:13:00 Delft Intercity
2023-05-15 00:29:00 Den Haag HS Intercity

由于文件只存储视图定义,无论所引用数据集增长到多大,它都保持很小。train_services.parquet 文件有 380,959 行,但读取它的目录只有几百千字节。

托管目录

将 rail_catalog.duckdb 上传到 DuckDB 可以通过网络读取的任何位置,例如 s3:// 存储桶或 https:// 端点。已经存放 Parquet 文件的同一个存储桶是放置它的便利位置。

共享目录然后意味着共享一个 URL,而不是一长串单独的文件路径。接收者不需要知道每个视图背后有多少文件或它们存储在哪里,只需要目录的地址。

以只读方式附加目录

消费者以只读方式附加目录,并像查询本地表一样查询视图。每个查询都从引用的文件读取当前数据,因此结果反映对象存储中那一刻的内容。

sql 复制代码
ATTACH 'https://example.com/rail_catalog.duckdb' AS rail (READ_ONLY);

SELECT station_name, count(*) AS calls
FROM rail.services
GROUP BY station_name
ORDER BY calls DESC
LIMIT 3;
station_name calls
Utrecht Centraal 7663
Amsterdam Centraal 7591
Zwolle 5013

消费者需要 httpfs 扩展,对于 s3:// 源,还需要授予对底层数据访问权限的凭据。DuckDB 只读取查询所需的列和行组,因此对大型远程数据集的过滤或聚合查询不会下载整个数据集。

在数据布局变化中存活

由于查询读取的是视图而不是直接读取文件,发布者可以更改文件而不更改查询。消费者在前后运行相同的查询。

假设单个 Parquet 文件变得太大,发布者将其拆分为每年一个文件。将视图更新为读取文件目录是目录中的一行更改,消费者什么也不会注意到。

sql 复制代码
CREATE OR REPLACE VIEW services AS
    SELECT *
    FROM read_parquet('s3://my-bucket/rail/services/year=*/*.parquet');

当文件更改时,视图还可以保持模式稳定。如果后来一批文件将 station_name 重命名为 station,视图可以将新列映射回消费者已经使用的名称。

sql 复制代码
CREATE OR REPLACE VIEW services AS
    SELECT
        * EXCLUDE (station),
        station AS station_name
    FROM read_parquet('s3://my-bucket/rail/services/*.parquet');

如果你重新分区文件或将它们移动到新存储桶,你只需更新目录。任何查询它的人都可以继续运行与之前相同的查询。

何时使用它

当你想要共享数据集而不向接收者发送一长串单独的文件路径,并且数据已经采用 DuckDB 读取良好的格式(例如 Parquet)时,请使用此模式。读者获得一组已命名的关系来查询,发布者可以更改文件布局而不破坏这些查询。

注意以下限制:

  • 消费者必须能够访问目录文件以及其视图引用的每个数据源。
  • 通过 HTTPS 和 S3 API 的连接是只读的,因此目录无法就地修改。要更改视图,请编辑本地副本并再次上传。
  • 查询性能取决于网络和所引用文件的布局。查询远程文件的提示适用。

结论

一个只包含视图的 DuckDB 文件是一个小目录,你可以作为单个 URL 共享。数据保持在其原始位置,发布者可以更改其存储方式,而读者获得一组稳定的关系来查询。

完整参考,请参阅《共享一个只存储视图的 DuckDB 数据库》指南。

相关推荐
SelectDB12 小时前
从 StarRocks 走向 Apache Doris:如何实现引擎平滑替换与架构升级?
大数据·数据库·数据分析
为思念酝酿的痛12 小时前
MySQL的操作
数据库·mysql
运维行者_12 小时前
网络监控工具怎么选?从设备监控到智能运维的能力清单
运维·服务器·开发语言·网络·人工智能·支持向量机·php
2401_8685347812 小时前
陈冲2026年上海纽约大学全英文毕业演讲
服务器·网络
猫咪很可爱12 小时前
Oracle ORA-4031 错误分析与处理:SGA 内存不足导致 update/exp/expdp 失败
数据库·oracle
小豆庄13 小时前
视频素材处理时的隐私盲区:云处理与本地处理的边界在哪
数据库·图像处理·视频·敏捷流程
Umi·14 小时前
MySQL库表操作
数据库·mysql
晚风吹北巷14 小时前
Linux复习篇(自用)
linux·运维·服务器·1024程序员节
风哥2号14 小时前
数据库教程FGMT69:PostgreSQL运维诊断与监控分析
运维·数据库·postgresql
ss27314 小时前
AI时代首先数据库-PostgreSQL实战笔记 27 PostgreSQL数据写入与读取流程解析
数据库·笔记·postgresql