holt-cj:720 行的图数据库,能干什么、干不了什么
内容提要
holt-cj 是基于 badger-cj 的嵌入式图数据库,约720行代码,支持顶点、边、多标签、JsonValue 属性、邻接索引、Gremlin 风格惰性遍历,以及事务与备份恢复。邻接查询通过索引较快,但未实现属性索引,has(key,value) 需全量过滤,V() 也全量扫描。适合以邻接查询为主的中小规模单机嵌入式场景,不适合属性检索、路径算法和十万级顶点。
延伸解读
索引设计决定查询快慢
holt-cj 的存储布局只有五种 key 前缀,其中 eout:、ein:、el: 三种是真正的邻接索引。这意味着按顶点查邻居、按谓词找边、按标签过滤顶点都能走前缀扫描,速度较快。但属性索引完全缺失,createIndex() 是空操作,getIndexes() 返回空列表。因此 .has(key, value) 只能把顶点读进内存逐个比较,代价与顶点总数成正比。选型时先看查询是否以邻接为主,否则会撞上性能墙。
V() 全量扫描的代价
遍历从 V() 开始时,execute() 会先扫 v: 前缀取出所有顶点 ID,再逐个 getVertex 做单点读,相当于一次全量扫描加 N 次读取。顶点数量到十万级时,这种起点方式会明显拖慢查询。文章建议尽量从 V(ids) 或已有顶点出发,而不是从 V() 开始。这提醒使用者:遍历的起点选择直接影响性能,在数据量增长后尤其要避免无指定起点的全量遍历。
定位是嵌入式小图库,不是轻量 Neo4j
文章用对比表明确划出边界:holt-cj 具备顶点、边、属性、多标签、邻接索引、基本 Gremlin 风格遍历和事务,但缺少属性索引、变长路径、最短路径、图算法和分布式能力。它适合几千到几万顶点、以邻接查询为主的单机嵌入式场景,例如 CLI 工具、离线分析、依赖关系图或测试替身。若需要按属性检索、路径算法或多进程共享,则应另选完整图数据库。
Q&A
holt-cj 是什么?它有哪些核心功能?
holt-cj 是一个基于 badger-cj 的嵌入式图数据库,只有约720行代码。它支持顶点、边、多标签、JsonValue 属性、邻接索引、Gremlin 风格惰性遍历,以及事务和备份恢复。
holt-cj 的存储结构是怎样的?哪些查询能走索引?
holt-cj 使用五种 key 前缀:v: 存顶点,e: 存边,eout: 存出边索引,ein: 存入边索引,el: 存边标签索引。因此,按顶点查邻接边(getOutgoingEdges/getIncomingEdges)和按标签查边(has(label))能走索引,速度快。
holt-cj 的属性过滤为什么慢?
因为 holt-cj 没有实现属性索引,createIndex() 是空操作。.has(key, value) 的实现是逐顶点过滤:把顶点读入内存后比较属性,代价与顶点总数成正比,数据量大时很慢。
holt-cj 适合用在哪些场景?
holt-cj 适合数据量中等(几千到几万顶点)、关系简单的本地图,查询以邻接为主;也适合嵌入式场景(CLI 工具、单机应用、离线分析)、不想为图关系写关联表的情况、测试替身以及一次性关系数据分析。
holt-cj 有哪些主要限制?
主要限制包括:属性索引未实现,按属性找顶点会全量过滤;不支持变长路径和最短路径等图算法;顶点数量到十万级以上时 V() 全量扫描会拖慢性能;不支持多进程共享图。
holt-cj 的遍历 API 怎么用?
holt-cj 提供 Gremlin 风格的惰性遍历,步骤包括 V()/V(ids)、hasLabel、has、out/in/both、limit、toList/next。遍历是惰性构建的,调用 toList() 或 next() 才真正执行。
holt-cj 和 Neo4j 这类完整图数据库差多远?
holt-cj 具备顶点、边、属性、多标签、邻接查询、基本遍历和事务,但缺少属性索引、变长路径、最短路径、图算法和分布式能力。它定位是嵌入式小图库,不是轻量版 Neo4j。