Datahike中pull-many查询400个实体速度慢,如何优化?
针对你用Datahike 0.6.1531查询400个实体耗时2900ms的问题,这不是EAV数据库的固有权衡,明显存在可优化的地方,具体建议如下:
改用Datalog批量查询替代
pull-many
当前用(range 1 400)遍历ID并逐个拉取实体的方式,会触发多次独立查询,每个ID都要去查找对应的属性条目,累加开销很高。换成Datalog一次性获取所有目标实体:(d/q '[:find (pull ?e [:db/id :resource-name :notable?]) :where [?e :resource-name]] ; 只匹配存在书名的实体,避免无效ID查询 @conn)这种方式会直接扫描所有包含
:resource-name属性的实体(即你的书籍),批量返回结果,大幅减少查询次数。避免查询无效ID
(range 1 400)包含了很多可能不存在的实体ID,Datahike需要逐个检查这些ID是否存在对应的属性,额外增加了不必要的IO和计算开销。通过Datalog的:where条件过滤出实际存在的书籍实体,只拉取有效数据。检查数据库后端配置
Datahike支持多种后端(内存、SQLite、PostgreSQL等),如果使用的是磁盘型后端(如SQLite),确保后端配置了合理的连接池、缓存策略。比如SQLite可以开启Write-Ahead Logging(WAL)模式提升读写性能,PostgreSQL则要确保连接数足够且索引配置合理。确认属性索引情况
虽然本次查询是拉取实体属性,但如果:notable?这类属性有频繁的过滤需求,可以为其创建索引。执行(d/transact @conn [{:db/ident :notable? :db/index true}])开启索引,后续涉及该属性的查询会更高效。
EAV模型确实在批量拉取固定属性集合的场景下,比传统行式数据库略逊一筹,但400个实体耗时近3秒属于异常情况,通过上述优化应该能将耗时降低到几百毫秒以内。
内容的提问来源于stack exchange,提问作者silian-rail

