【开源自荐】SlothDB —— 零依赖嵌入式分析数据库,用 SQL 直接查询 CSV/Parquet/JSON/Excel 文件

你好,

想向小众软件推荐 SlothDB ------ 一款开源嵌入式分析数据库引擎(Windows / Mac / Linux,MIT 协议)。

SlothDB 属于嵌入式 OLAP 引擎,直接链接到应用里使用,不需要启动数据库服务器。最核心的特点是「不导入、直接查」:指向一个
CSV、Parquet、JSON、Excel 文件,就能用标准 SQL 跑聚合、过滤、JOIN、窗口函数等查询。7
种文件格式全部内置在单个可执行文件里,不需要装任何扩展:CSV、Parquet、JSON / NDJSON、Excel (.xlsx)、Avro、Arrow IPC、SQLite。

支持 130+ 个 SQL 功能,包括窗口函数、递归 CTE、QUALIFY、MERGE、复杂子查询等;单文件 .slothdb
持久化,原子性检查点;可选 GPU 加速(NVIDIA CUDA / Apple Metal,大数据集自动启用)。提供 CLI shell、Python 绑定(pip
install slothdb,结果可直接转 pandas DataFrame)、C/C++ API(稳定 C ABI,可嵌入任何应用)。

用 C++20 从零写的,采用向量化列式执行、morsel 驱动的并行处理、mmap 文件 I/O 等现代 OLAP 技术。跨平台支持 Windows /
Linux / macOS,当前版本 v0.1.2。

仓库:GitHub - SouravRoy-ETL/slothdb: An OLAP analytical database engine built in C++20. Query CSV, Parquet, JSON, and Excel with SQL. 1.1×–6.6× faster than DuckDB on every format. · GitHub

我在 Linux Mint 22.3(64 位版)上测试了 0.1.0 版本,发现几个问题:

编辑完帖子再去项目主页,发现刚刚下载的 slothdb_0.1.2_amd64.deb 好像被楼主删了?

1 交互 shell 中,遇到汉字时需要按两次删除键才能完全删掉

首先,按下删除键后,如果碰到汉字,需要按两次删除键才能删掉(只按一次后会留下一个空格),比如这样(_ 表示光标位置)

slothdb> select * from 测试_

按一次删除键后会变成:

slothdb> select * from 测 _

再按一次删除键后才能完全删除:

slothdb> select * from 测_

2 对中文的支持不好

似乎无法读取中文列名。

3 交互 shell 中无法用方向键移动光标

后是输入 ^[[D,而非移动光标,感觉使用体验不是很好。

建议模仿 bash 那种交互:

  • 移动光标
  • 转到上一条、下一条历史记录

4 程序内的帮助信息过于简单了

进入交互 shell,输入 .help ,只能看到如下信息:

SlothDB Shell vSlothDB 0.1.0
Type .help for help, .quit to exit.

Connected to in-memory database
slothdb> .help   
.help     Show this help
.quit     Exit
.tables   List all tables
.schema   Show table schemas
.version  Show version
slothdb> 

至于怎么打开文本文档,怎么开始查询,这些基本信息一概没有。

感谢您的详细反馈!您报告的 4 个问题在 v0.1.2 里全部修复了。坦白说,这些都是真实的 bug,不是「用户使用方式的问题」------您的 Linux Mint 测试指出了 SlothDB 在中文环境下几个严重的缺失,非常感谢。

4 个问题的修复状态

1. 交互 shell 中汉字按一次删除键只能删半个字 → 已修复

原因:v0.1.0 的 shell 用 std::getline 读输入,终端处于 canonical 模式,按字节而不是按 UTF-8 字符回删。v0.1.2 集成了
antirez 的 linenoise 库(MIT 协议),按真正的 UTF-8 字符边界删除,一次按键删一个汉字。

2. 无法读取中文列名 → 已修复

原因:SQL tokenizer 用 std::isalpha / isalnum 判断标识符,这两个函数对高位字节(汉字 UTF-8 编码都是 ≥ 0x80)返回
0,所以汉字列名直接报 Unexpected character。v0.1.2 修改了 tokenizer,把所有高位字节都视为标识符字符。

现在可以直接写:

CREATE TABLE 销售 (区域 VARCHAR, 销售额 BIGINT);
INSERT INTO 销售 VALUES ('华东', 100), ('华南', 200), ('华东', 50);
SELECT 区域, SUM(销售额) FROM 销售 GROUP BY 区域 ORDER BY 区域;
-- 华东 | 150
-- 华南 | 200

也能直接查中文表头的 CSV:SELECT 区域 FROM '数据.csv'。日语、韩语、任何 UTF-8
字符都支持,规则是「所有高位字节都算标识符字符」,不做语言特判。

3. 方向键显示 ^[[D 而不是移动光标 → 已修复

原因:canonical 模式下方向键产生的 ESC 序列被 getline 当成普通字符读入。linenoise 切换到 raw 模式并自己解析 ESC
序列。现在:

  • / 移动光标
  • / 浏览历史记录
  • Ctrl+A / Ctrl+E 跳到行首/行尾
  • Tab 补全 SQL 关键字和 dot 命令
  • 历史记录自动保存在当前目录 .slothdb_history 文件里

4. .help 信息太简单 → 已修复

v0.1.2 的 .help 现在会列出:

  • 所有 dot 命令:.help / .quit / .tables / .schema / .open / .version / .clear
  • 7 种文件格式的查询示例(CSV / Parquet / JSON / Excel / Avro / Arrow / SQLite)
  • 持久化表的用法
  • 多行输入规则(分号结尾才执行)
  • 快捷键说明

新增的 dot 命令:

  • .tables [PATTERN] ------ 列出所有表(可选 LIKE 模式)
  • .schema [TABLE] ------ 查看表结构
  • .open <path> ------ 关闭当前 DB 切换到另一个
  • slothdb --version / slothdb --help ------ 命令行参数

如何升级到 v0.1.2

下载地址: Release v0.1.2 · SouravRoy-ETL/slothdb · GitHub

Linux (.deb):

wget https://github.com/SouravRoy-ETL/slothdb/releases/download/v0.1.2/slothdb_0.1.2_amd64.deb
sudo dpkg -i slothdb_0.1.2_amd64.deb

Linux (二进制直接运行):

wget https://github.com/SouravRoy-ETL/slothdb/releases/download/v0.1.2/slothdb
chmod +x slothdb
./slothdb

Python:

pip install --upgrade slothdb

之前的 slothdb_0.1.2_amd64.deb 确实被我重新打包过好几次(修了 macOS 构建错误 + 补了这些中文相关的
bug),导致下载链接一度 404,不好意思。现在 release 稳定了,不会再动。

如何验证修复

安装后进入交互 shell,跑一遍您之前踩过的几个场景:

$ slothdb
SlothDB Shell v0.1.2
Type .help for help, .quit to exit.

Connected to in-memory database
slothdb> .help                            # 应该看到完整帮助
slothdb> CREATE TABLE 测试 (名称 VARCHAR, 数量 BIGINT);
slothdb> INSERT INTO 测试 VALUES ('甲', 10), ('乙', 20);
slothdb> SELECT 名称, 数量 FROM 测试;     # 中文列名能查
slothdb> SELECT * FROM 测试_              # 按一次退格,整个汉字被删
slothdb> SELECT * FROM 测试;              # ↑ 可以找到刚才那条历史
slothdb> .quit

还有一个遗留问题(坦白告知)

shell 输出含汉字的表格时,列宽用的是字节数不是显示宽度,汉字在终端占 2 个字符宽但代码按 1
算,所以对齐会有点歪。数据完全正确,只是视觉对齐。后续会用 wcswidth 修掉,这个算是 v0.1.3 的 TODO。

再次感谢您的详细 bug 报告 ------ 您发现的每一个问题都是真实的、应该修的 bug,不是「用了错误的姿势」。如果 v0.1.2
上还遇到其他问题,欢迎在 GitHub
Issues(https://github.com/SouravRoy-ETL/slothdb/issues)继续反馈,或者直接在这里回我。

1 个赞

顶一下帖子。请各位帮忙提供一些反馈意见

顶一下帖子。请各位帮忙提供一些反馈意见

请勿多次自己顶帖,谢谢。

1 个赞

用 SQL 语法查询 CSV 文件么?

我有个疑问:这是否和 SQLite 有点点类似?

1 个赞

SQLite 的话,需要先把 csv 文件导入到 SQLite 数据库中,作为一张表,然后进行查询。

而楼主这个软件不需要这一步,可以直接对 csv 文件进行查询。

其实这个软件的性质更接近 awk,都是直接对文本文件内容进行分析。

2 个赞

这是一款 OLAP 数据库,支持您在 AWS EC2 或任何其他机器上进行本地文件查询,且速度极快,响应时间仅在毫秒级。它支持所有主流文件格式,包括 Parquet、CSV、S3、HTTPS、JSON、NDJSON、Excel、Avro、Arrow IPC 以及 SQLite。该数据库能够创建表、视图和实时视图以满足大规模数据分析需求,并能彻底免除您原本在 Snowflake 或 Databricks 等平台上产生的全部计算成本。https://slothdb.orgduckdb.org 的一款替代方案。

测试了一下 0.1.4 版本,发现 2 楼提到的问题都已经解决了。

再说几个个人关于功能和使用上的设想和建议:

1 建议软件遇到语句语法错误后不要直接退出,而是先回到 shell

否则,每次打开都要重新加载一次数据库,有点麻烦。

2 建议加一个输出查询结果到 csv、tsv 等形式文件的功能

很多时候我查询 csv 文件不只是为了看结果,更多的是要把筛选出的数据交给其他软件使用。

3 可否考虑增加多表外连接查询功能?

我这边很多数据表之间是有一定关联的,如果能用 SQL 外连接那种形式进行查询应该会更方便。

否则,如果只能对单个 csv 文件进行查询,那其实和 awk 也没什么区别了。

感谢您的测试以及条理清晰的反馈。这三个问题均已在 0.1.5 版本中得到解决,新版本刚刚发布:

Shell 因语法错误而退出 ------ 位于 tools/shell/shell.cpp 中的 REPL(交互式解释器)现在能够捕获错误并继续运行;我无法复现 Shell 实际退出的情况。如果您能提供导致程序退出的具体查询语句,我将追踪那个未被捕获的特定代码路径并进行修复。

将查询结果导出为 CSV / TSV 格式 ------ 此功能目前已可用:

COPY (SELECT * FROM 'large.csv' WHERE year >= 2023) TO 'filtered.csv';

自 0.1.5 版本起,当源数据使用"裸文件字面量"(即不带额外修饰的文件名)时,上述命令也能正常工作了(此前该组合曾存在故障,现已修复)。若需导出为 TSV 格式,可通过 WITH (DELIMITER '\t') 参数指定分隔符。至于提供一个更简短的 Shell 点命令(如 .output filtered.csv ...)作为快捷方式,这属于"锦上添花"的功能需求,目前已列入待办追踪列表。

多文件外部连接(Outer JOIN)------ 我已复现该 Bug,并在 0.1.5 版本中将其修复。现在,针对不同 CSV 文件执行文件字面量连接(File-literal JOIN)的操作已能正常运行:

SELECT u.name, o.amount FROM 'users.csv' u LEFT JOIN 'orders.csv' o ON u.id = o.user_id;

该功能同样适用于 INNER(内连接)、RIGHT(右连接)以及 FULL OUTER(全外连接)。相关的三种子用例均已包含在回归测试中(详见 test/unit/storage/test_csv.cpp)。

您可以通过 pip install --upgrade slothdb(获取 0.1.6 版本)或 npm install @slothdb/wasm(获取 0.1.7 版本)来获取最新代码。包含上述修复的在线浏览器演示环境(Playground)现已更新并上线,访问地址:https://slothdb.org/playground。

一个小小的请求:您提出的建议极具价值,且显然您已对本项目进行了深入研读。不知您是否愿意以协作者(Collaborator)的身份加入本项目的代码仓库?我很乐意为您在 SouravRoy-ETL/slothdb 仓库中开通写入权限(Write Access)。具体而言,成为协作者后:

像您刚才提出的这类问题,可以直接提交至 GitHub Issues 专区,从而便于进行系统化的追踪与管理。
项目路线图(ROADMAP.md)中规划了一个"功能对标冲刺周期"(Parity Sprint),旨在实现 DESCRIBESUMMARIZEEXPLAIN ANALYZE 以及 PRAGMA 自省等功能 ------ 我非常乐意将其中任何一项任务的负责人角色移交给您。毕竟,目前绝大多数初次接触本项目的用户都是通过那个在线演示环境(Playground)来了解和体验项目的;如果能收到来自实际工作负载用户的 UX 反馈,那将非常有价值。
如果您有意愿,请留下您的 GitHub 用户名,我会向您发送邀请。如果您觉得"协作者"身份权限过高,也可以直接在代码仓库中针对这三个具体事项提交 Issue------这样也能确保相关反馈不会遗漏。

在 shell 中,输入 .open [文件名] 打开数据文件时,如果文件名不带引号,则程序会崩溃:

% ./slothdb
SlothDB Shell v0.1.4
Type .help for help, .quit to exit.

Connected to in-memory database
slothdb> .open test.csv
Failed to open: test.csv
[1] % _

感谢你提供了如此详尽的复现步骤------问题确实出在那个未受保护的退出路径上。修复代码已合并至 main 分支(提交 ID:8725c45),且已随 0.1.5 版本发布至 GitHub。

问题所在:
.open 命令在尝试打开新数据库之前,会先关闭当前数据库。一旦新的打开操作失败,系统便无法找到有效的句柄可供回退,导致处理程序返回了错误码 1------从而导致整个 Shell 彻底退出,而非回退至命令提示符状态。

修复方案:
.open 命令现在的逻辑是:首先尝试打开新数据库,仅在打开成功后才进行数据库句柄的切换。若打开失败,程序会打印错误信息并回退至 slothdb> 命令提示符状态;此前的会话状态将保持活跃。
此外,如果失败的目标路径看起来像是一个数据文件(如 .csv、.parquet、.json、.arrow、.xlsx 或 .tsv 格式),错误提示信息中现在也会建议正确的操作命令:
slothdb> .open test.csv
打开失败:test.csv
提示:.open 命令仅用于打开持久化的 .slothdb 数据库文件。若要查询数据文件,请使用:
SELECT * FROM ‘test.csv’;
slothdb>
如果你之前的协作邀请依然有效,我仍非常乐意接受------随时欢迎通过 GitHub 账号向我发送邀请。

楼主的回复怎么一股AI味 :joy:

1 个赞

不是 100% HAI 泰铢翻译

What’s this?

我本想表达的意思并非指"AI",但我确实使用了 Google 翻译。非常抱歉!

个人感觉 DeepL(https://www.deepl.com/)的翻译效果似乎更好一点,您可以试一试。

另外,如需回复某个帖子,请点击帖子右下角的 “回复” 按钮,否则被回复者无法收到消息:

谢谢。你能根据你的反馈查看最新的修改内容吗?另外,你能成为 slothDB 项目的贡献者吗?

谢谢,但本人没有程序开发能力,且平日工作繁忙,无法参与到您的项目中。