Datomic 超过 GC 开销限制

Datomic exceed GC overhead limit

尝试使用此查询对数据中的实体进行计数

(d/q '[:find (count ?a) . :where [?a :type]] (d/db (conn)))

OutOfMemoryError GC overhead limit exceeded  [trace missing]

工作思路,如果我尝试计算较小的子集,例如

(d/q '[:find (count ?a) :where [?a :type "psp"]] (d/db (conn)))

[[400541]]

使用开发后端。

是我做错了什么,还是我应该尝试不同的后端,或者别的什么?

这是堆栈跟踪 http://pastebin.com/C76mEhEJ,它指向 datomic.datalog.

中的某处

Datomic 中的查询很急切。即使在使用聚合时,也会实现整个中间表示。在您的情况下,这是数据库中所有实体的实体 ID、类型、值部分的所有元组的集合。当整个中间集无法在内存中实现时,您会看到这样的错误,但您的查询结构不是 Datomic 可以天真地告诉将进行数据库扫描的结构(在那些情况下它会抛出)。

如果您正在扫描整个数据库,datoms - 记录在案 here - 更适合,因为它将懒惰地遍历与前缀匹配的所有数据。对于您的用例,使用 datoms 进行数据库扫描的惰性 seq 方法可能类似于:

(count (dedupe (map #(:e %) (seq (d/datoms (d/db conn) :aevt :type)))))

这会从 :aevt 索引中获取所有具有属性 :type 的数据(该属性是缩小结果范围的前导组件)。我们将 datoms 输出处理为 seq,并从每个数据中获取 :e(实体 ID),进行重复数据删除,因此我们只计算唯一实体。如果这是一个基数属性,您可以避免此 dedupe 步骤。