Skip to content

Instantly share code, notes, and snippets.

@jonase
Created July 25, 2012 11:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jonase/3175654 to your computer and use it in GitHub Desktop.
Save jonase/3175654 to your computer and use it in GitHub Desktop.
query performance predictability
(use '[datomic.api :only [db q] :as d])
(def schema
[{:db/id #db/id[:db.part/db]
:db/ident :num
:db/valueType :db.type/long
:db/cardinality :db.cardinality/one
:db.install/_attribute :db.part/db}
{:db/id #db/id[:db.part/db]
:db/ident :parent
:db/valueType :db.type/ref
:db/cardinality :db.cardinality/one
:db.install/_attribute :db.part/db}])
(defn make-tree [root node-fn child-count-fn depth]
(if (zero? depth)
(node-fn)
[root
(map #(make-tree % node-fn child-count-fn (dec depth))
(repeatedly (child-count-fn) node-fn))]))
(defn num-tree [root]
(make-tree root #(rand-int 9) #(inc (rand-int 5)) 5))
(defmulti emit (fn [pid o] (type o)))
(defmethod emit Number [pid n]
(let [id (d/tempid :db.part/user)]
[[:db/add id :num n]
[:db/add id :parent pid]]))
(defmethod emit clojure.lang.IPersistentVector [pid [root children]]
(let [id (d/tempid :db.part/user)]
(concat [[:db/add id :num root]]
(when pid [[:db/add id :parent pid]])
(mapcat #(emit id %) children))))
(def num-db
(let [uri "datomic:mem://numtrees"]
(d/delete-database uri)
(d/create-database uri)
(let [conn (d/connect uri)]
(d/transact conn schema)
;; Add 20 trees with roots numbered from 100 to 119
(doseq [n (range 100 120)]
(d/transact conn (emit nil (num-tree n))))
(db conn))))
(def descendant
'[[[descendant ?a ?b] ;; ?b is a descendant of ?a if
[?b :parent ?a]] ;; ?b:s parent is ?a
[[descendant ?a ?b] ;; or
[?x :parent ?a] ;; the parent of ?x is ?a
[descendant ?x ?b]]]) ;; and ?x is a descendant of ?a
(dotimes [_ 5]
(time
(q '[:find ?desc
:in $ %
:where
[?root :num 100]
[descendant ?root ?desc]]
num-db descendant)))
;; ~20 msecs
(dotimes [_ 5]
(time
(q '[:find ?desc
:in $ %
:where
[?root :num 100]
[descendant ?root ?desc]
[?desc :num 4]]
num-db descendant)))
;; ~3000 msecs
(dotimes [_ 5]
(time
(q '[:find ?desc
:in $ %
:where
[?root :num 100]
[descendant ?root ?desc]
[?desc :num ?n]
[(= ?n 4)]]
num-db descendant)))
;; back to ~20 msecs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment