ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

sqlite-vec:JDBC 三步接入向量搜索

sqlite-vec:JDBC 三步接入向量搜索 sqlite-vecJDBC 三步接入向量搜索【免费下载链接】sqlite-vecA vector search SQLite extension that runs anywhere!项目地址: https://gitcode.com/GitHub_Trending/sq/sqlite-vecsqlite-vec 是一个用纯 C 写的 SQLite 向量搜索扩展零外部依赖哪里能跑 SQLite 哪里就能跑它。在 Java 项目里通过 JDBC 驱动加载这个扩展向量入库和最近邻检索的完整闭环只要三步建一张 vec0 虚拟表、插几行数据、发一条 MATCH 查询。不用部署独立的向量数据库也不用为几千条 embedding 专门养一台服务。向量不是数组Java 里第一个坑从 Java 写向量数据时最容易犯的错误是把向量当成float[]数组直接往里塞。vec0 表接收向量有两种格式JSON 文本[0.1, 0.2, 0.3]这种字符串或者紧凑的二进制字节串每个 float 占 4 字节的原始 bytes。对 JDBC 场景来说最省事的办法就是走 JSON 文本路径——把向量拼成字符串传给setString即可。先用 JDBC 把扩展加载进来这一步和后面建表、查询用的是同一个连接Class.forName(org.sqlite.JDBC); try (Connection conn DriverManager.getConnection(jdbc:sqlite:sample.db); Statement stmt conn.createStatement()) { // SQLite 默认禁止加载扩展这里显式打开 stmt.execute(SELECT load_extension(./vec0)); // 顺手验证一下扩展真的生效了 ResultSet rs stmt.executeQuery(SELECT vec_version()); if (rs.next()) { System.out.println(vec 版本: rs.getString(1)); } }扩展的获取方式有两条路直接用 GitHub Releases 里的预编译产物.so/.dylib/.dll或者把仓库克隆下来自己编译——源码就是一个sqlite-vec.cmake一下就行。源码仓库地址git clone https://gitcode.com/GitHub_Trending/sq/sqlite-vec编译细节可以看仓库里的 site/compiling.md。一张 vec0 表三种列各干各的事建表前值得花两分钟搞清 vec0 的列定义语法因为它和普通的CREATE TABLE不太一样。同一张表里列按职责分成三类向量列embedding float[384]指定维度这是 KNN 搜索的目标元数据列普通列定义比如content text好处是能出现在 KNN 查询的WHERE里做过滤分区键加partition key后缀向量索引会按这个值内部分片让只搜某一类的查询快得多。CREATE VIRTUAL TABLE document_embeddings USING vec0( document_id integer, embedding float[384], category_id integer partition key, content text );这里document_id和content是元数据列category_id是分区键。一个实用原则分区键的每个取值下最好有上百条向量切得太碎比如按单条记录分反而会拖慢 KNN。如果只想把大块文本挂在向量旁边、不参与过滤可以把列名前面加辅助列查询结果里能直接带出来省掉一次 JOIN。一条 MATCH 查询拿到 K 个最近邻插入向量就是把普通数据当参数传进去String insertSQL INSERT INTO document_embeddings(rowid, document_id, embedding, content) VALUES (?, ?, ?, ?); try (PreparedStatement pstmt conn.prepareStatement(insertSQL)) { pstmt.setInt(1, 1); pstmt.setInt(2, 1001); pstmt.setString(3, [0.1, 0.2, 0.3, /* ... 共 384 维 */ 0.5]); pstmt.setString(4, 示例文档内容); pstmt.executeUpdate(); }检索时MATCH后面跟查询向量结果按distance距离越小越相似排序String searchSQL SELECT rowid, document_id, content, distance FROM document_embeddings WHERE embedding MATCH ? ORDER BY distance LIMIT 10; try (PreparedStatement searchStmt conn.prepareStatement(searchSQL)) { searchStmt.setString(1, [0.15, 0.25, 0.35, /* ... */ 0.4]); ResultSet rs searchStmt.executeQuery(); while (rs.next()) { System.out.println(rs.getInt(document_id) distance rs.getDouble(distance) rs.getString(content)); } }如果数据带分区把category_id ?加进WHEREsqlite-vec 会在搜索前先按分区过滤只扫自己那份向量这是大表上最直接的提速手段。更多表结构和查询写法可以参考 site/features/vec0.md。批量灌数据事务比什么都重要一条一条executeUpdate加自动提交往表里灌一万条向量会慢得难以忍受——每次提交都伴随一次磁盘落盘。正确姿势是关自动提交、攒批次、手动提交conn.setAutoCommit(false); try (PreparedStatement pstmt conn.prepareStatement(insertSQL)) { for (int i 0; i 10000; i) { pstmt.setInt(1, i); pstmt.setInt(2, 100000 i); pstmt.setString(3, vectorAsJson(i)); // 384 维向量 pstmt.setString(4, doc- i); pstmt.addBatch(); if (i % 500 0) { pstmt.executeBatch(); conn.commit(); // 每 500 条提交一次平衡速度与回滚代价 } } pstmt.executeBatch(); conn.commit(); } finally { conn.setAutoCommit(true); }除了事务规模上来之后还有两个杠杆一是用分区键缩小搜索范围前面提过二是向量维度尽量贴实际模型输出别声明 768 维却只填 384 个值维度不匹配会直接报错。完整的调优思路见 site/guides/performance.md。扩展加载失败按顺序查这三处load_extension报错是 JDBC 集成里最常见的失败点按命中概率从高到低排路径不对。./vec0是相对路径指向的是 JVM 进程的工作目录不是你放代码的目录。用绝对路径最稳或者确认文件名没漏平台后缀Linux 下是vec0.somacOS 是vec0.dylib。平台不匹配。预编译扩展是按操作系统和 CPU 架构打包的拿 Linux 的.so去 Windows 上加载必然失败。不确定就回到源码自己编译Makefile 会自动识别 Linux / macOS / Windows。SQLite 版本太旧。JDBC 驱动自带的 SQLite 版本如果低于扩展编译时的版本加载会报符号错误。升级org.xerial:sqlite-jdbc到较新版本通常能解决。另外两个小习惯能避免后续排查困难连接用完记得关闭try-with-resources写起来就是上面代码的样子避免扩展占用的内存和句柄不释放每次加载后跑一句SELECT vec_version()留档确认线上跑的是预期版本。最后留一句具体建议上线前先用几百条真实向量把建表 → 批量插入 → MATCH 检索整条链路跑通一遍重点验证向量维度和模型输出维度严格一致——这一步出问题后面所有排错都白搭。【免费下载链接】sqlite-vecA vector search SQLite extension that runs anywhere!项目地址: https://gitcode.com/GitHub_Trending/sq/sqlite-vec创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表