如何使用Datomic分区?

时间:2017-11-24 16:31:16

标签: clojure datomic

我想使用Datomic分区来提高应用的可扩展性。

首先,我首先在事务中创建了一个分区:

{:db/id "communities"
   :db/ident :communities}
 [:db/add :db.part/db :db.install/partition "communities"]

其次,我在另一个事务中创建了数据库模式:

{:db/ident :person/name
 :db/valueType :db.type/string
 :db/cardinality :db.cardinality/one
 :db.install/_attribute :communities}

{:db/ident :person/age
 :db/valueType :db.type/int
 :db/cardinality :db.cardinality/one
 :db.install/_attribute :communities}

{:db/ident :person/sibblings
 :db/valueType :db.type/int
 :db/cardinality :db.cardinality/one
 :db.install/_attribute :communities}

以下是一个简单查询的示例:

(d/q '[:find ?name ?age
       :where
       [?p :person/name ?name]
       [?p :person/age ?age]]
   db)

当我发出此查询时,出现以下错误:

Unhandled datomic.impl.Exceptions$IllegalArgumentExceptionInfo :db.error/not-an-entity Unable to resolve entity: :person/name {:db/error :db.error/not-an-entity}

当我为每个属性替换:db.install/_attribute :communities :db.install/_attribute :db.part/db时,查询工作正常。我对其他所有查询都有同样的问题。

我错过了什么吗?

1 个答案:

答案 0 :(得分:3)

用户定义的分区不是替代"链接点"用于用户定义的属性。属性始终通过:db.part/db属性 1 链接到:db.install/attribute实体,并且它们始终位于:db.part/db分区中。

分区允许您确保与某些实体相关的数据通过确保其实体ID在特定范围内分配而在Datomic的索引中紧密相连。如果您的应用可能会同时访问驻留在某个分区中的实体,则可能会提高查询的性能。还可以遍历与驻留在某个分区中的实体相关的数据,而不会遇到不相关的数据(使用seek-datoms + EAVT + entid-at)。

一旦定义分区,使用分区的方法是在创建新实体时将其:db/ident传递给datomic.api/tempid(或者您可以将其与#db/id标记的文字一起使用edn files):

@(d/transact connection
   {:db/id (d/tempid :some-partition)
    … …})

如果您随后发出了一个查询,该查询恰好提取了与该实体相关的一些EAVT块,那么这些块可能会包含有关同一分区中其他实体的信息(除非该实体在其上声明了足够多的属性以进行填充一个块,我想......但即便如此,你也会在索引树中获取一些相关节点),这样你的对等体就可以从缓存中检索有关它们的信息。

如果您希望从这种类型的地方看到主要好处,那么分区可能值得研究。如果您不确定自己的应用会受益,那就完全没问题。显然,这个功能在野外并没有被广泛使用,实际上新的( - )客户端API目前根本没有公开它。

1 虽然注意到自0.9.5530以来明确的:db.install/_attribute :db.part/db行是不必要的:Datomic现在推断新引入的实体是来自&#的存在的属性34;属性属性" :db/ident:db/valueType:db/cardinality - 这是可能的,因为后两者仅由属性使用 - 并为您添加:db.install/attribute链接。