【问题标题】:Are there any difference calling `run.db` once and multiple times in Slick在 Slick 中一次和多次调用“run.db”有什么区别吗
【发布时间】:2021-09-24 07:43:02
【问题描述】:

调用run.db一次有什么区别:

val dbAction3 = for {
  res1 <- dbAction1
  res2 <- dbAction2(res1)
} yield res2

val res3 = db.run(dbAction3)

多次:

val res3 = for {
  res1 <- db.run(dbAction1)
  res2 <- db.run(dbAction2(res1))
} yield res2

据我了解,除非我们在第一个中使用transactionally,否则没有区别。

【问题讨论】:

  • 这个问题缺少很多重要信息。请显示类型范围内可用的任何内容。具体来说,这些 db 操作是什么类型(或者您认为它们是),以及什么类型是 db.此代码是否编译,或者您在此处引用的代码?因为照原样,这段代码显然没有。在不了解预期范围内的更多信息的情况下,这个问题的信息太少,我自己无法弄清楚。
  • 我不是说它可以编译。我试图从不必要的细节中抽象出真正的问题。我猜,按类型,你的意思是读像select 这样的查询,写像insertupdate 这样的查询。我们可以评估不同类型组合的问题。例如,两者都是读取查询,或者都是写入查询,或者其中一个被读取而另一个被写入。

标签: scala slick


【解决方案1】:

两者的可观察效果是相同的,但它们的执行方式不同。第一个版本创建一个传递给数据库的查询,而第二个版本创建两个单独的数据库查询。

如果两个操作之间存在任何共性,则第一个版本提供了更大的优化潜力。 (例如,如果两个操作都使用相同的表/视图)。一个好的数据库可能能够以单独查询无法实现的方式组合或重新排序操作以提高效率。

第二个版本会产生两个数据库操作的开销,并使用Future 机制来序列化它们而不是内部数据库机制,因此可能效率较低。

第一个版本没有缺点,它可能会更有效地执行,所以这是“更好”的选择。但它确实取决于特定的数据库实现,因此可能存在第二个版本更快的情况。

【讨论】:

  • 感谢您的回答。我有一些后续行动。考虑一个您尝试逐步分解为微服务的单体系统。在这种情况下,如果我们不需要transactionally,我似乎有必要使用 Future(第二个选项),因为它会使调用外部服务更容易。另外,想想更大的fors 有 10-20 个查询,我们确定 Slick 会创建优化的单个查询吗?
  • 另外,如果第一个创建单个查询(我使用 PostgreSQL 顺便说一句),为什么我们甚至需要transactionally? PostgresSQL 已经提供了这一点(参见this doc 中的第一句话)。
  • 我应该更准确地说“操作”而不是“查询”,因为即使是单个 Slick 操作也可以包含多个操作(例如 DBIO.sequence)。您的特定操作从dbAction1 获取结果并将其传递给dbAction2,因此必须有两个单独的操作。所以如果没有transactionallydbAction1dbAction2 之间可能会发生任何事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-22
  • 1970-01-01
  • 1970-01-01
  • 2021-06-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多