2017-04-12 97 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分鐘的平均去除。我會說每個任務在任何時候平均有大約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

開始剖析等之前,你可以更換

[:find ?taskIds ...] 

通過

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

減少往返到對等的數量,從而獲取task-entities擺脫地圖聲明。在第二步中,用你真正想要爲每個實體提供的適當的密鑰集替換[*]

+0

我試過這個,我的印象是,它加快了一點,但它仍然平均約20秒左右。基本上我想拉所有的鑰匙,所以我不認爲取代[*]會很重要。還有什麼我可以嘗試嗎? – Johan

+0

抱歉,我不知道;應該正確設置索引,因爲:tenant/guid是唯一的。我注意到的唯一的錯誤是模式中的以下錯字: :db/ident:tenant/taks – fricke

+0

我也嘗試過拉特定屬性,但它似乎沒有任何區別。你認爲這是值得嘗試的Datomic Pro和SQL作爲後端,而不是使用Datomic Free? – Johan