【问题标题】:Wrap Slick queries in Futures在 Futures 中包装 Slick 查询
【发布时间】:2013-11-07 23:26:35
【问题描述】:

我正在尝试使用 Slick 异步查询 MySQL 数据库。下面的代码模板,我用来在 for comprehension 中查询大约 90k 行,最初似乎可以正常工作,但该程序消耗了几 GB 的 RAM,并且在大约 200 次查询后失败且没有警告。

import scala.slick.jdbc.{StaticQuery => Q}
def doQuery(): Future[List[String]] = future {
  val q = "select name from person"
  db withSession {
    Q.query[String](q).list
  }
}

我尝试使用fromURL 方法和c3p0 连接池来设置连接。我的问题是:这是对数据库进行异步调用的方式吗?

【问题讨论】:

  • 如果你使用db withSession { implicit session :Session =>会有什么行为?仅供参考,不鼓励threadLocalSession
  • 我可以使用什么(以及如何)代替threadLocalSession,或者在哪里可以找到有关可用会话类型的文档?
  • 从 withSession 调用中获取会话,而不是像我写的 db withSession { implicit session :Session =>
  • 问题是在上面的代码中db代表一个数据库连接而不是一个会话。我假设由于大多数(全部?)文档示例在执行查询时都使用db,所以这实际上是会话。现在效果很好,另请参阅related Github issue 上的评论。

标签: scala future slick


【解决方案1】:

Async 仍然是 open issue for Slick

您可以尝试使用 Iterables 和流数据,而不是将其存储在内存中,解决方案类似于:Treating an SQL ResultSet like a Scala Stream

尽管最后请省略 .toStream 调用。它会将数据缓存在内存中,而Iterable不会。

如果你想要一个异步版本的 iterable,你可以查看 Observables

【讨论】:

  • 感谢您的回答并指出我的问题。另见my comment
  • 很高兴我能指出你正确的方向。你的解决方案很好,干得好;)
【解决方案2】:

事实证明这不是问题(实际上是我的代码中的一个错误,它为每个查询打开了一个新的数据库连接)。根据我的经验,您可以将 DB 查询包装在 Futures 中,如上所示,稍后使用Scala AsyncRx 组合它们,如here 所示。获得良好性能所需要的只是一个大线程池(在我的例子中是 CPU 的两倍)和一个同样大的连接池。

【讨论】:

    【解决方案3】:

    Slick 3 (Reactive Slick) 看起来可能会解决这个问题。

    【讨论】:

    • 虽然理论上这可以回答这个问题,it would be preferable 在这里包含答案的基本部分,并提供链接以供参考。
    猜你喜欢
    • 2014-06-19
    • 2017-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-11
    • 2013-10-31
    • 2016-01-23
    • 1970-01-01
    相关资源
    最近更新 更多