나는 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를 사용하고 있습니다. 당신이 등 프로파일 링을 시작하기 전에
병목 현상을 찾기 위해 코드의 프로파일을 작성했다면 도움이 될 것입니다. Tufte 라이브러리를 사용하여이를 수행 할 수 있습니다. –
엔티티가 아닌 끌어 오기 API를 사용하면 더 나은 결과를 얻을 수 있습니다 (나중에 반환 된 결과를 변환 할 수 있음). –
@ValentinWaeselynck는 팁을 주셔서 감사 드리며, 다시 시도하겠습니다. – Johan