提问人:silian-rail 提问时间:10/31/2023 最后编辑:silian-rail 更新时间:11/6/2023 访问量:80
使用“pull”(datahike)检索 400 个实体的属性的慢速查询
Slow query using `pull` (datahike) to retrieve attributes on 400 entities
问:
我在 JVM 上使用 Datahike 0.6.1531(不是 Datomic)。我有一个要在 Web 应用程序中显示的书名列表。如果这本书是“值得注意的”,我会做一些特别的事情,比如应用背景色或附加表情符号。
我想返回一个类似于以下内容的向量:
[{:db/id 339, :resource-name "Notation as a Tool of Thought"}
{:db/id 338, :resource-name "The Science of Radio", :notable? :true}
{:db/id 337, :resource-name "Journey Into Mathematics"}
{:db/id 336, :resource-name "Street Fighting Mathematics"}
...]
在 400 个左右的实体范围内使用 3 个 attr-id(包括 )执行以下查询需要 ~2,900 毫秒:pull-many
:db/id
(require '[datahike.api :as d]) ; version 0.6.1531
(d/pull-many @conn [:db/id :resource-name :notable?]
(range 1 400))
查询时间慢是 EAV 数据库的固有权衡,还是我未能以某种非常明显的方式进行优化?
答:
这个问题最初出现在 Clojurians slack 的 DataHike 频道中,所以我从那里将我的答案编辑成一个更长的单篇文章答案。DataHike 是 Clojure/ClojureScript 中 Datalog 查询引擎的众多实现之一。
由于您使用的是普通的 JVM Clojure(它往往是性能最高的),因此我希望得到更快的结果。我从 Datomic 获得的经验是,这样的查询应该快很多倍。
DataScript(这是 DataHike 最初基于的数据日志实现)有时可能有点慢,但对于 clojure/script 环境来说,结果似乎有点太慢了。
DataScript 中 pull-api 的实现与 DataHike 中 pull-api 的实现是完全不同的,其中 DataHike 似乎比 DataScript 做了更多的簿记和检查(这使得 DataHike 慢得多,但也更容易让它正常工作)。
JIT/更好的性能指标
您的查询最多包含数据库中的 400 个实体。这可能很少有人触发 JIT 重新编译/优化(这就是在长时间运行的生产代码中使这一切更快的原因)。像 Criterium (clojure) 或 Tufte (Criterium 的 ClojureScript 移植)这样的工具将运行大量测试,以确保 JVM 或 JavaScript VM 是“热的”,大多数 JIT 优化已经到位。
我建议您使用 Criterium 或 Tufte 测试性能。
DataHike 仍然更具实验性(但可用),并且与 DataScript 具有不同的范围,这可能会使查询引擎慢得多,但它应该不会这么慢(恕我直言)。
Datahike 维护者在此拉取请求中解决并解决了此问题: https://github.com/replikativ/datahike/pull/653
评论
datahike