使用“pull”(datahike)检索 400 个实体的属性的慢速查询

问题描述 投票:0回答:1

我正在使用 Datahike 0.6.1531(不是 Datomic)。我有一个要在网络应用程序中显示的书名列表。如果这本书“值得注意”,我会做一些特别的事情,例如应用背景颜色或附加表情符号。

我想返回一个类似于这样的向量:

[{: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(包括

pull-many
)的
:db/id
查询需要约 2,900 毫秒:

(require '[datahike.api :as d]) ; version 0.6.1531
(d/pull-many @conn [:db/id :resource-name :notable?] 
  (range 1 400))

缓慢的查询时间是 EAV 数据库固有的权衡,还是我未能以某种非常明显的方式进行优化?

clojure datomic
1个回答
1
投票

这个问题最初出现在 Clojurians slack 的 DataHike 频道中,所以我将那里的答案编辑为更长的单个帖子答案。 DataHike 是 Clojure/ClojureScript 中 Datalog 查询引擎的众多实现之一。

您没有提及您正在使用哪个 Clojure 环境。如果您使用 Babashka,它是解释性的,因此非常慢,查询时间可能是合理的。

如果您使用普通的 JVM Clojure(往往性能最高),我希望得到更快的结果。我从 Datomic 获得的经验是,这样的查询应该快很多倍。

DataScript(DataHike 最初基于的数据记录实现)有时可能会有点慢,但对于 clojure/script 环境来说,结果似乎仍然有点太慢。

DataScriptpull-api的实现与DataHikepull-api的实现有很大不同,其中DataHike似乎比DataScript做了更多的簿记和检查(这使得DataHike更慢,而且也更容易让它正常工作)。

JIT/更好的性能指标

您的查询最多包含数据库中的 400 个实体。这可能很少会触发 JIT 重新编译/优化(这使得在长时间运行的生产代码中这一切变得更快)。 Criterium (clojure) 或 Tufte(Criterium 的 ClojureScript 端口)等工具将运行大量测试,以确保 JVM 或 JavaScript VM 是“热”的,并且大多数 JIT 优化已经就位。

我建议您使用 Criterium 或 Tufte 测试性能。

DataHike 仍然更具实验性(但可用),并且具有与 DataScript 不同的范围,这可能会使查询引擎仍然慢得多,但它不应该这么慢。

© www.soinside.com 2019 - 2024. All rights reserved.