1

我正在 play framework 2.0 中尝试一个简单的 scala 代码来填充我的数据库(存在其他选项,例如直接在数据库中导入 SQL 文件,但这不是重点):

def filldb = Action {
  import play.api.db.DB
  import anorm._

  var result: Boolean = false

  val tuples: List[(Long, String)] = DB
    .withConnection("playground") { implicit c =>

      for (i <- 1 until 1000000) {
        SQL("""
            INSERT INTO article (
                id,
                title
            ) VALUES (
                """ + i + """,
                'Article no """ + i + """');"""
        ).executeUpdate()

        if (i % 1000 == 0) println("i:" + i)
      }

      val sqlQuery = SQL("select id, title from article order by id;")

      sqlQuery().map(row =>
        row[Long]("id") -> row[String]("title")).toList
    }
  Ok("done")
}

这运行了一段时间(200K 迭代),速度变慢,逐渐消耗内存(高达 1.8GB),最后因内存不足而崩溃。

有人可以解释一下导致这种行为的原因吗?很明显,可以用不同的方式对其进行编码,但关键是要了解什么是错误的,这样错误就不会在另一个上下文中发生......

为了完整起见,以下是详细信息:

  • 操作系统:mac 10.6.8
  • 播放:2.0
  • 数据库:mysql 5.5.12
  • 桌子 :

    CREATE TABLE article (
    id bigint(20) NOT NULL UNIQUE,
    title varchar(255) NOT NULL,
    PRIMARY KEY (id)
    );
    

也试过这个,没有更多的成功:

def filldb = Action {
  import play.api.db.DB
  import anorm._

  var result: Boolean = false
  val connection = DB.getConnection("playground")

  for (i <- 1 until 1000000) {
        SQL("""
            INSERT INTO article (
                id,
                title
            ) VALUES (
                """ + i + """,
                'Article no """ + i + """');"""
        ).executeUpdate()(connection)

        if (i % 1000 == 0) println("i:" + i)
      }

  val tuples: List[(Long, String)] = {

      val sqlQuery = SQL("select id, title from article order by id;")

      sqlQuery()(connection).map(row =>
        row[Long]("id") -> row[String]("title")).toList
    }

  connection.close()

  Ok("done")
}

不是更好:停留在 283k 次迭代...

4

2 回答 2

0

我的第一个猜测是您可能仍在使用内存数据库中的默认值。你能检查并确保你的 conf/application.conf 没有使用 jdbc:h2:mem:play 吗?如果是这样,您的所有条目都会填满您的记忆。

此外,您所做的每条语句都会打开一个语句对象,该对象在 withConnection 块结束之前不会关闭。既然你有一百万个坐在记忆中,那就可以建立起来了。见http://www.playframework.org/documentation/2.0/ScalaDatabase

您可以尝试在查询操作之外填充数据库。我会尝试做 1000 批,每批 1000 批,看看是否能确定你的问题。

于 2012-03-22T21:39:02.467 回答
0

我认为您的问题出在此处:

val tuples: List[(Long, String)] = {

  val sqlQuery = SQL("select id, title from article order by id;")

  sqlQuery()(connection).map(row =>
    row[Long]("id") -> row[String]("title")).toList
}

您正在使用数据库中的所有行填充地图,因此您正在使用 1M 行填充 Scala/Java 数据结构。

你真的需要一百万行吗?或者您是否需要以分页方式(即前 20 个、第二个 20 等)。

这不是播放问题,即使使用 java 和单个普通 jdbc 测试,您也会遇到同样的问题。告诉我们元组的真实用法,我们可以提供一些建议。

于 2013-11-12T13:07:40.753 回答