2016-02-02 176 views
0

试图计数datomic实体与此查询Datomic超出GC开销限制

(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内的某处。

+0

你的堆设置是什么?这看起来像你没有足够的内存用于中间表示(仍然是一组元组,尽管你已经集合了它)。 –

+0

@BenKamphaus如果我正确地理解了jvm选项,我的初始和最大堆大小是2Gb和4Gb,这里是jvm输出http://pastebin.com/eRpEXEuv,试图用“-Xmx6g”“-Xms4g”运行,结果和这几乎是我所有的公羊。顺便说一句,你是什么意思的中间结果,'?a'(整个数据集)在我的情况? – cvb

+1

是的,Datomic中的查询是渴望的,查询中的聚合对所有匹配[_:type _ _ _]的元组进行操作。你可以尝试使用datoms进行数据库扫描的懒序列操作,例如:(count(dedupe(map#(:e%)(seq(d/datoms(d/db conn):aevt:type)))) )' –

回答

1

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

如果你正在扫描整个数据库,datoms - 记录here - 是一个更好的选择,因为它会懒洋洋地遍历所有匹配前缀的数据。对于DB扫描与datoms懒惰序列的方法为您的使用情况下,可能是这样的:

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

这得到所有datoms从具有属性:type(该属性是然后缩小的主要成分:aevt指数结果)。我们将datoms输出作为seq处理,并从每个数据库中获取:e(实体ID),并进行重复数据删除,以便我们只计算唯一的实体。如果这是一个基数属性,你可以避免这个步骤dedupe

相关问题