2017-04-12 12 views
2

私はDatomicデータベースで次のようになりスキーマを持っている:Datomicクエリパフォーマンスの向上

; --- tenant 
{:db/id     #db/id[:db.part/db] 
:db/ident    :tenant/guid 
:db/unique    :db.unique/identity 
:db/valueType   :db.type/string 
:db/cardinality  :db.cardinality/one 
:db.install/_attribute :db.part/db} 
{:db/id     #db/id[:db.part/db] 
:db/ident    :tenant/name 
:db/valueType   :db.type/string 
:db/cardinality  :db.cardinality/one 
:db.install/_attribute :db.part/db} 
{:db/id     #db/id[:db.part/db] 
:db/ident    :tenant/taks 
:db/valueType   :db.type/ref 
:db/cardinality  :db.cardinality/many 
:db.install/_attribute :db.part/db} 

; --- task 
{:db/id     #db/id[:db.part/db] 
:db/ident    :task/guid 
:db/unique    :db.unique/identity 
:db/valueType   :db.type/string 
:db/cardinality  :db.cardinality/one 
:db.install/_attribute :db.part/db} 
{:db/id     #db/id[:db.part/db] 
:db/ident    :task/createdAt 
:db/valueType   :db.type/instant 
:db/cardinality  :db.cardinality/one 
:db.install/_attribute :db.part/db} 
{:db/id     #db/id[:db.part/db] 
:db/ident    :task/name 
:db/valueType   :db.type/string 
:db/cardinality  :db.cardinality/one 
:db.install/_attribute :db.part/db} 
{:db/id     #db/id[:db.part/db] 
:db/ident    :task/subtasks 
:db/valueType   :db.type/ref 
:db/cardinality  :db.cardinality/many 
:db.install/_attribute :db.part/db} 

; --- subtask 
{:db/id     #db/id[:db.part/db] 
:db/ident    :subtask/guid 
:db/valueType   :db.type/string 
:db/cardinality  :db.cardinality/one 
:db/unique    :db.unique/identity 
:db.install/_attribute :db.part/db} 
{:db/id     #db/id[:db.part/db] 
:db/ident    :subtask/type 
:db/valueType   :db.type/string 
:db/cardinality  :db.cardinality/one 
:db.install/_attribute :db.part/db} 
{:db/id     #db/id[:db.part/db] 
:db/ident    :subtask/startedAt 
:db/valueType   :db.type/instant 
:db/cardinality  :db.cardinality/one 
:db.install/_attribute :db.part/db} 
{:db/id     #db/id[:db.part/db] 
:db/ident    :subtask/completedAt 
:db/valueType   :db.type/instant 
:db/cardinality  :db.cardinality/one 
:db.install/_attribute :db.part/db} 
{:db/id     #db/id[:db.part/db] 
:db/ident    :subtask/participants 
:db/valueType   :db.type/ref 
:db/cardinality  :db.cardinality/many 
:db.install/_attribute :db.part/db} 

; --- participant 
{:db/id     #db/id[:db.part/db] 
:db/ident    :participant/guid 
:db/valueType   :db.type/string 
:db/cardinality  :db.cardinality/one 
:db/unique    :db.unique/identity 
:db.install/_attribute :db.part/db} 
{:db/id     #db/id[:db.part/db] 
:db/ident    :participant/name 
:db/valueType   :db.type/string 
:db/cardinality  :db.cardinality/one 
:db.install/_attribute :db.part/db}  

タスクが時間をかけてかなり静的ですが、サブタスクを一度タスクごとの5分あたり平均約追加および削除され。私は、平均して各タスクには、1人の参加者を含む(ほとんどの場合、ただし例外はいくつかあります)いつでも約40のサブタスクがあると言います。 Datomicを使用する私の唯一の目的は、時間の経過とともにタスクがどのように進化したかを見ることです。つまり、ある時点でタスクがどのように見えるかを確認したいのです。達成するために、私は現在これに似た何かをしています:

(defn find-tasks-by-tenant-at-time 
    [conn tenant-guid ^long time-epoch] 
    (let [db-conn (-> conn d/db (d/as-of (Date. time-epoch))) 
      task-ids (->> (d/q '[:find ?taskIds 
           :in $ ?tenantGuid 
           :where 
           [?tenantId :tenant/guid ?tenantGuid] 
           [?tenantId :tenant/tasks ?taskIds]] 
          db-conn tenant-guid) 
         vec flatten) 
      task-entities (map #(d/entity db-conn %) task-ids) 
      dtos (map (fn [task] 
       (letfn [(participant-dto [participant] 
          {:id (:participant/guid participant) 
          :name (:participant/name participant)}) 
         (subtask-dto [subtask] 
          {:id   (:subtask/guid subtask) 
          :type   (:subtask/type subtask) 
          :participants (map participant-dto (:subtask/participants subtask))})] 
        {:id  (:task/guid task) 
        :name  (:task/name task) 
        :subtasks (map subtask-dto (:task/subtasks task))})) task-entities)] 
      dtos)) 

残念ながら、これは非常に遅いです。テナント(約20名)に約40のサブタスクを含む多くのタスクがある場合、この関数から戻るまでに約60秒かかることがあります。私はここで間違って何かをしていますか?これをスピードアップすることは可能ですか?

更新: データセット全体はおよそ2Gbで、ピアには3.5Gbのメモリがあります(しかし、1.5Gbと言うとそれを減らしても差は出ません)。トランザクタには1Gbのメモリがあります。私はDatomic Freeを使用しています。あなたがなどプロファイリングを開始する前に

+0

ボトルネックを見つけるためにコードをプロファイリングしておけば、助けが簡単になります。これを行うには、Tufteライブラリを使用します。 –

+0

エンティティではなくプルAPIを使用すると、より良い結果を得ることができます(返された結果を後で変換できます)。 –

+0

@ValentinWaeselynckはこのヒントをお寄せいただきありがとうございます。 – Johan

答えて

2

あなたは、ピアへのラウンドトリップの回数を減らすために、したがって、task-entitiesの地図声明を取り除く

[:find (pull ?task-entity [*]) ...] 

によって

[:find ?taskIds ...] 

を置き換えることができます。 2番目のステップでは、[*]の代わりに、それぞれのエンティティを実際に取りたい適切なキーのセットに置き換えます。

+0

私はこれを試してみましたが、私の印象はそれが少しスピードアップしていますが、それでも約20秒ほどで平均化されています。基本的に私はすべてのキーを引っ張りたいので、[*]を置き換えるのは大したことではないと思います。私が試すことができる何か他にありますか? – Johan

+0

申し訳ありませんが分かりません。テナント/ GUIDが一意であるため、インデックスを正しく設定する必要があります。私が気がついたのは、スキーマ内の次のタイプミスです。 :db/ident:tenant/taks – fricke

+0

私は今も特定の属性を取得しようとしましたが、何の違いもありません。 Datomic Freeを使用する代わりにDatomic Proを試して、SQLをバックエンドとして使用する価値があると思いますか? – Johan

関連する問題