seekdb [1] 是一个支持 SQL、全文检索和向量搜索的 AI 数据库。现在,我们把 seekdb 编译成了 WebAssembly(Wasm),塞进了浏览器!
数据库引擎就在你本机的浏览器里运行,不需要连接云端数据库。 应用只要把 seekdb 嵌进浏览器,不用搭后端,就能直接建表、写数据,做全文检索、向量搜索、混合搜索和 FORK TABLE。除了浏览器,seekdb 也能跑在 Wasmtime、Wasmer 这类 Wasm runtime 里,作为插件嵌进其他系统。
一、快速体验
为了方便你体验 seekdb WebAssembly,我们上线了:在线体验页面 [2](https://www.seekdb.ai/shell/)。
这是一个嵌入了 seekdb 的网页应用,只需在浏览器里打开,不需要安装任何依赖,就能直接跑 SQL。我们还内置了混合搜索和 FORK TABLE 两个 demo,点一下按钮就能运行,帮你快速熟悉 seekdb 的 AI 功能。

混合搜索能在一条 SQL 里同时做全文匹配、条件过滤和向量距离排序,适合知识库检索、RAG 这类既要关键词准确、又要语义相关的场景,不用把全文检索和向量检索分开查、再自己合并结果。

点击 Run Hybrid Search,示例会创建一张同时带全文索引和向量索引的表,然后执行:
SELECT id,
body,
l2_distance(embedding, '[1,0,0]') AS distance
FROM shell_hybrid_demo
WHERE MATCH(body) AGAINST('database')
AND category = 'docs'
ORDER BY distance APPROXIMATE LIMIT 3;

FORK TABLE 能从一张表分出一份独立的副本,AI Agent 或开发者可以在副本上随意修改和试错,原表不受影响。

点击 Run Fork Table,示例会创建表
shell_fork_notes 并写入两行,再用一条 SQL 分出新表
shell_fork_draft,之后两张表各改各的,互不影响:
FORK TABLE shell_fork_notes
TO shell_fork_draft;

shell 默认用内存模式,数据放在 Wasm 内存里,刷新页面就没了。切到 OPFS 模式后,数据会写进 OPFS,也就是浏览器给每个网站的私有存储,刷新页面、关掉浏览器再打开都还在。

把右上角的存储模式从 Temporary (Memory) 切到 Persistent (OPFS),在弹出的确认框里点确定,然后建一张表、写一行:
CREATE DATABASE IF NOT EXISTS demo;
USE demo;
CREATE TABLE notes (
id INT PRIMARY KEY,
body VARCHAR(100));
INSERT INTO notes
VALUES (1,
'刷新页面之前写入的');
刷新页面,再查一下,数据还在:
SELECT * FROM demo.notes;

编译成 Wasm 之后,seekdb 既能嵌进浏览器,也能嵌进浏览器之外的系统。
浏览器内。 把 seekdb 嵌进网页之后,前端不用后端,也能自己存数据、查数据。比如 AI 应用可以把文档、对话记录和它们的 embedding 存在用户的浏览器里,用混合搜索直接在页面里检索。这样做有三个好处:
离线读写:页面加载完成后,读写数据都不需要网络。
数据留在本地:数据存在用户自己的浏览器里,查询时也不用上传到服务器,适合笔记、本地文件这类不想离开本机的数据。
查询在本机执行:省掉了到服务器的网络往返,延迟更低;服务端也不用为这些查询运行数据库,成本更低。
在浏览器外, seekdb 也可以作为 Wasm 插件,嵌进内置了 Wasm runtime 的系统。
常见的 Wasm runtime 有 Wasmtime 和 Wasmer,还有多用在云原生和边缘计算的 WasmEdge,以及体积小、适合嵌入式设备的 WAMR。宿主系统需要时加载 seekdb,用完就卸载,不用为数据库单独部署和运维,就有了存储和检索数据的能力。
这些能力,靠的是 Wasm 本身的特点:插件跑在严格隔离的沙箱里,冷启动快,也不限宿主系统用哪种编程语言。适合那些需要自带数据库、对隔离要求高、逻辑相对独立的系统。
Wasm 模块自己只能做计算,开线程、读写文件这些事,都要靠运行它的宿主提供。浏览器和 Wasm runtime 提供这些能力的方式不一样,所以 seekdb 在两边的编译方式和用法也不一样。
seekdb 主要用 C++ 编写,也引入了一部分 Rust 代码。
我们用 Emscripten 把它编译成两部分:一个 .wasm 文件,里面是整个数据库引擎;一段 JavaScript 代码,也就是 JS glue。

浏览器负责运行 .wasm,引擎需要的线程和文件则由 JS glue 用浏览器自己的接口来提供:线程用 Web Worker 实现,数据文件交给 Emscripten 的 WasmFS,放在 Wasm 内存里,或者写进 OPFS。
浏览器里既监听不了 TCP 端口,也用不了 Unix socket,所以我们用内存模拟了 socket:在 seekdb 用 Rust 实现的网络层里,client 和引擎通过两段内存队列互相收发 MySQL 协议的 packet。
对引擎来说,它和真的 socket 连接没有区别,处理 MySQL 协议的代码照常工作。

部署时,网页要通过 HTTPS 或 localhost 访问,并带上
Cross-Origin-Opener-Policy: same-origin 和
Cross-Origin-Embedder-Policy: require-corp 两个响应头:引擎的多线程依赖 SharedArrayBuffer,浏览器只在这种情况下才允许使用它。
Wasm runtime 里没有浏览器,也就没有 JS glue,这时要把 seekdb 按 WASI(WebAssembly [3] System Interface)编译。

WASI 是 Wasm 模块和 runtime 之间约定好的一套系统接口,包括读写文件、读取时钟等,由 runtime 直接实现,Wasmtime、Wasmer 都支持。
宿主程序把 runtime 嵌进自己的进程,加载 seekdb 的 .wasm,再调用它导出的函数打开数据库、执行 SQL。数据文件放在宿主程序授权的目录里:按照 WASI 的规定,模块只能访问 runtime 明确交给它的目录,碰不到宿主机上的其他文件。


OB Cloud 企业新用户提供专享,点击免费申请 >>
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69909943/viewspace-3188677/ ,如需转载,请注明出处,否则将追究法律责任。