数据原子查询性能改进

2024-03-03

我在 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 秒的时间。我在这里做明显错误的事情吗?有可能加快这个速度吗?

更新: 整个数据集大约为 2 Gb,对等方有 3.5 Gb 内存(但如果我将其减少到 1.5 Gb,似乎没有任何区别),而交易者有 1 Gb 内存。我正在使用 Datomic 免费版。


在开始分析等之前,您可以替换

[:find ?taskIds ...]

by

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

减少到对等点的往返次数,从而消除了 map 语句task-entities。在第二步中替换[*]使用您真正想要为每个实体提取的适当的密钥集。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数据原子查询性能改进 的相关文章

  • Scala - Java = ? (或者 Clojure - Java = ?)

    开发人员可以在不懂 Java 的情况下使用 Scala 吗 开发人员可以在不懂 Java 的情况下使用 Clojure 吗 注意 例如 我是一名 C 开发人员 我在不了解任何 VB 的情况下使用 NET 当然 WF 4 0 使用 VB 进行
  • Leiningen 在构建可用的 uberjar 时遇到问题

    我们正在尝试与 Leiningen 一起构建我们的 Clojure 项目 我们通过执行以下操作成功创建了 uberjar 前提条件 project clj 文件列出了依赖项 main my project core在项目 clj中 core
  • 原子聚合的使用

    我想在下一个查询中找到年龄最小的人 d q find name min age in name age John 20 Bill 25 Jack 20 Steve 28 Andrew 30 但结果是 Andrew 30 Bill 25 Ja
  • Clojure:只能从尾部位置重复

    我正在尝试递归地反转列表 但是我得到了Can only recur from tail position运行时 这到底意味着什么 如何改进我的代码才能使其正常工作 defn recursive reverse coll loop coll
  • Clojure def 与 defn 对于没有参数的函数

    我用 clojure 编写了一个程序 但有些函数没有参数 将此类函数编码为 def 而不是不带参数的 defn 有什么优点 def t0 System currentTimeMillis defn t1 System currentTime
  • clojure 有 AES 库吗?

    clojure 有 AES 加密库吗 我应该使用通过 maven 或 clojars 提供的 java 库吗 感谢您的时间和考虑 下面是一个使用可用的 java 加密库的可能更惯用的示例 encrypt and decrypt这里每个都简单
  • 有没有好的 Clojure 基准测试?

    Edit Clojure 基准测试已达到基准游戏 http benchmarksgame alioth debian org u64q clojure html 我已经制作了这个问题社区维基并邀请其他人保持更新 有人知道 Clojure 性
  • Clojure 符号名称中的美元符号 ($)

    我一直在编写 clojure 解析器并遇到以下语法 defn key Returns the key of the map entry added 1 0 static true java util Map Entry e e getKey
  • 为什么我的字符串函数返回 clojure.lang.LazySeq@xxxxxx?

    我使用 leiningen REPL 定义了以下 3 个函数 defn rand int range floor ceiling floor rand int ceiling floor defn mutate index mutates
  • 与doseq(或for)并行遍历集合的有效方法?

    doseq e coll1 myfunc e 如果您只关心副作用 那么速度非常快 如果我想要怎么办myfunc 并行 地从多个集合中获取元素 即 applymyfunc到每个集合的第一个元素 然后到所有第二个元素 然后到所有第三个元素 依此
  • Clojure 缩减函数的目的

    clojure 的目的是什么reduced函数 在 Clojure 1 5 中添加 https clojure github io clojure clojure core api html clojure core reduced htt
  • 竞争条件和 Clojure Atoms

    clojure atom 的文档指出 Changes to atoms are always free of race conditions 然而 竞争条件不仅是根据更改定义的 而且是在不同线程中并行逻辑操作的上下文中定义的 我想知道 保证
  • Clojure 的映射和减少 Monad...Juxt Monad 怎么样?

    在学习 Clojure 的过程中 我花了很长时间试图理解 monad 它们是什么以及我们如何使用它们 但没有取得太大成功 然而 我发现了一个很棒的 Monads for Dummies 视频系列 http vimeo com 2071730
  • 如何解构向量以用作函数参数

    在 Python 中 您可以将列表或元组传递给函数并让函数解压参数 我怎样才能在 Clojure 中做到这一点 下面是一些 Python 代码示例 def f a b c d print a a print b b print c c pr
  • 将嵌套映射分解为键值对

    我想将 Clojure 中的嵌套映射分解为一系列键值对 例如 我们有这张地图 a b c d e f g h i j 分解后的地图应如下所示 a b c d e f g h i j d e f g h e f g h i j 输出的顺序并不
  • 如何在 repl 中加载新的 clojure 库

    所以我有这个工作流程问题 我很高兴在我的 clojure 项目 repl 上打字 并意识到我需要另一个不在我的库中的库project clj 在这种情况下 我需要tools cli图书馆 我打开project clj在我的编辑器中添加一个条
  • 在 Clojure 中的函数上使用“apply”时,如何显式指定名称空间?

    这里的 graph 是高阶函数 它返回一个在其范围内设置了配置的函数 ns bulbs neo4jserver graph defn out1 Test func that simply returns out1 config out1 d
  • 如何将目录添加到 Clojure 的类路径?

    我已使用 Maven 将库安装到 m2 repository 目录中 我想将该路径添加到默认的 Clojure 类路径中 我找不到如何执行此操作的文档 有什么提示吗 Cheers clj Clojure 1 4 0 user gt requ
  • Clojure 为什么命名为 Clojure

    为什么该语言的名称是 Clojure 我用谷歌搜索了一下 在 clojure 中询问 到目前为止 还没有运气 Rich Hickey 他是 Clojure 的设计者 对此的评论是 wiki 上的第一个参考链接 您是否根据以 closure
  • Clojure 宏总是泄漏吗?

    如果你读过这个问题宏 gt 带有匿名函数 https stackoverflow com questions 10740265 macro with anonymous functions 10740411 comment13981517

随机推荐

  • 在 Team Foundation Server 中实际使用 Mercurial?

    我的商店使用 TFS 并且总体上对它很满意 但缺少本地存储库提交 恢复 我开始自己在本地使用 Mercurial 来帮助管理较小的更改块 然后将它们发布到 TFS 我看到 Subversion 有一个 桥接 组件 如果中央 VCS 是 Su
  • Celery 任务已收到但未执行

    我有已收到但不会执行的 Celery 任务 我正在使用 Python 2 7 和 Celery 4 0 2 我的消息代理是 Amazon SQS 这是的输出celery worker celery worker A myapp celery
  • ASP.NET Core 应用程序中project.json 中的构建选项下的preserveCompilationContext 有什么用?

    我是 ASP NET Core 新手 我试图了解 project json 中的各种选项 但无法理解其含义保留编译上下文 true在project json 中的构建选项下 据微软称文档 https learn microsoft com
  • 如何将 HSB 转换为 RGB

    我有一台德尔福XE2项目 https stackoverflow com questions 17729550 how can you change the font color using timer control改变Label01 F
  • 捏合缩放 ListView Android

    我正在尝试在 Android 上实现捏合放大列表视图 当我单击并拖动缩放的列表视图时遇到问题 首先 这是代码 public class ScaleListView extends ListView private ScaleGestureD
  • NSOrderedSet 生成的访问器中抛出异常

    在我的 Lion 应用程序上 我有这个数据模型 关系subitems inside Item 已订购 Xcode 4 1 内部版本 4B110 已为我创建了该文件Item h Item m SubItem h and SubItem h 这
  • Vue 3 Teleport 只能在 vue 之外移植吗?

    Vue 3 有一个新的 Teleport 功能 它取代了 vue 2 中的 Portal vue 插件 但是 我发现无法将组件移植到由 vue 控制的位置 在 vue 应用程序中 它仅在移植到外部 主体 其他元素 时才有效 const ap
  • Joomla 数据库 - 如何在 getQuery 中使用 LIMIT?

    我想使用 joomla 内置数据库类构建以下查询 SELECT FROM table name ORDER BY id DESC LIMIT 1 这是我到目前为止建立的查询 db JFactory getDBO query db gt ge
  • 为什么 setTimeout() 在 Chrome DevTools 下使我的调用堆栈变得混乱?

    我有一个函数 在完成后使用 setTimeout 重新排队 有人可以解释为什么 Chrome DevTools 让它看起来像是递归调用自己吗 我的理解是每次调用的调用堆栈都应该清晰 举这个非常简单的例子 第一次命中断点时 我看到 经过 3
  • Pandas:无法附加和重新分配到函数内的 DataFrame

    我想要做的是附加到一个 DataFrame 该 DataFrame 作为参数传递给函数 类似于以下代码中按函数完成的操作f df pd DataFrame data 0 1 0 1 columns a b df Out 58 a b 0 0
  • 如何删除 Django 自动生成的 ManyToMany 表中的冗余 ID 字段?

    我的班级有两节课models py file class Person person name models CharField max length 50 class Course course name models CharField
  • iPhone:检测自上次屏幕触摸以来用户不活动/空闲时间

    有没有人实现了一项功能 如果用户在一段时间内没有触摸屏幕 您会采取特定的操作 我正在努力找出最好的方法来做到这一点 UIApplication 中有这个有点相关的方法 UIApplication sharedApplication idle
  • 如何定义多重复合函数?

    有没有一种方法可以定义一个 Haskell 函数 它接受函数 某种集合 并生成单个函数 它们从右到左的组合 I tried foldr 但这只接受其结果与其参数具有相同类型的函数列表 foldr a gt a gt a gt a 所以 我可
  • 在 Amazon EC2 Windows 实例中自动挂载 EBS 卷

    有谁知道如何自动挂载弹性块存储 http aws amazon com ebs 在 Amazon 中启动 Windows 2003 实例时的 EBS 卷弹性计算云 http aws amazon com ec2 EC2 Setup 确保 E
  • 在 IntelliJ Idea 中调试时避免 Groovy/Grails 内部机制

    我正在使用 IntelliJ Idea 8 1 2 进行 Grails 开发 Groovy 的动态特性让我很难调试代码 我总是陷入 Groovy Grails 的内部 即 CachedMethod ExpandoMetaClass 等 例如
  • 不包含多个特定单词的字符串的正则表达式

    我正在尝试组合一个正则表达式来查找特定单词don t存在于字符串中 具体来说 我想知道什么时候 主干 标签 或 分支 不存在 这是针对 Subversion 预提交挂钩 基于正则表达式匹配不包含单词的字符串 https stackoverf
  • DLL 的配置文件

    我们的应用程序在运行时从应用程序的根加载我们的自定义 DLL 这些 DLL 正在实现某些接口 并通过反射执行方法 如果自定义 DLL 必须从配置文件中读取某些值 那么我们必须将这些配置设置复制到主应用程序的 app config 文件中 有
  • Scrapy Image Pipeline:如何重命名图像?

    我有一个蜘蛛可以获取数据和图像 我想用我正在获取的相应 标题 重命名图像 以下是我的代码 蜘蛛1 py from imageToFileSystemCheck items import ImagetofilesystemcheckItem
  • .cpp 文件和 .h 文件有什么区别?

    因为我已经做了 cpp文件 然后将它们传输到 h文件 我能找到的唯一区别是你不能 include cpp文件 我缺少什么区别吗 C 构建系统 编译器 不知道有什么区别 所以这都是约定之一 约定是 h文件是声明 并且 cpp文件是定义 这就是
  • 数据原子查询性能改进

    我在 Datomic 数据库中有一个与此类似的架构 tenant db id db id db part db db ident tenant guid db unique db unique identity db valueType d