我正在努力加快“SELECT * FROM WHERE name =?” Play中的一些查询! + Scala app。我正在使用Play 2.4 + Scala 2.11 + play-slick-1.1.1包。该软件包使用Slick-3.1版本。
我的假设是,slick会从DBIO操作生成Prepared语句并执行它们。所以我尝试缓存它们买入开启标志 cachePrepStmts = true 但是我仍然在日志中看到“正在准备语句...”消息,这意味着PS没有被缓存!应该如何指示光滑缓存它们?
如果我运行以下代码,不应该在某个时候缓存PS吗?
for (i <- 1 until 100) {
Await.result(db.run(doctorsTable.filter(_.userName === name).result), 10 seconds)
}
Slick config如下:
slick.dbs.default {
driver="slick.driver.MySQLDriver$"
db {
driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/staging_db?useSSL=false&cachePrepStmts=true"
user = "user"
password = "passwd"
numThreads = 1 // For not just one thread in HikariCP
properties = {
cachePrepStmts = true
prepStmtCacheSize = 250
prepStmtCacheSqlLimit = 2048
}
}
}
更新1
我按照@ pawel建议使用编译查询尝试了:
val compiledQuery = Compiled { name: Rep[String] =>
doctorsTable.filter(_.userName === name)
}
val stTime = TimeUtil.getUtcTime
for (i <- 1 until 100) {
FutureUtils.blockFuture(db.compiledQuery(name).result), 10)
}
val endTime = TimeUtil.getUtcTime - stTime
Logger.info(s"Time Taken HERE $endTime")
在我的日志中,我仍然看到如下声明:
2017-01-16 21:34:00,510 DEBUG [db-1] s.j.J.statement [?:?] Preparing statement: select ...
此时的时间也保持不变。什么是所需的输出?我不应该再看到这些陈述吗?如何验证Prepared语句是否确实被重用。
答案 0 :(得分:2)
您需要使用Compiled
个查询 - 这些查询正是您想要的。
只需将以上代码更改为:
val compiledQuery = Compiled { name: Rep[String] =>
doctorsTable.filter(_.userName === name)
}
for (i <- 1 until 100) {
Await.result(db.run(compiledQuery(name).result), 10 seconds)
}
我在name
上面提取了一个参数(因为你通常想要改变PreparedStatement
中的一些参数),但这绝对是一个可选部分。
有关详细信息,请参阅:http://slick.lightbend.com/doc/3.1.0/queries.html#compiled-queries
答案 1 :(得分:1)
对于MySQL,您需要设置一个额外的jdbc标志useServerPrepStmts=true
HikariCP的MySQL configuration page链接到一个非常有用的文档,它为MySQL jdbc提供了一些简单的performance tuning配置选项。
以下是我发现有用的一些内容(您需要&
将它们附加到jdbc url,以获取Hikari API未公开的选项。请务必阅读每个选项的链接文档和/或MySQL文档;应该 主要安全使用。
zeroDateTimeBehavior=convertToNull&characterEncoding=UTF-8
rewriteBatchedStatements=true
maintainTimeStats=false
cacheServerConfiguration=true
avoidCheckOnDuplicateKeyUpdateInSQL=true
dontTrackOpenResources=true
useLocalSessionState=true
cachePrepStmts=true
useServerPrepStmts=true
prepStmtCacheSize=500
prepStmtCacheSqlLimit=2048
另请注意,每个线程都会缓存语句;根据您为Hikari连接maxLifetime
设置的内容和服务器负载,服务器和客户端的内存使用量将相应增加(例如,如果将连接最大生命周期设置为MySQL默认的8小时,服务器和客户端将N个准备好的语句保存在内存中,以保证每个连接的生命周期。)
P.S。好奇,如果瓶颈确实是语句缓存或Slick特有的东西。
修改的
到log语句启用查询日志。在MySQL 5.7上,您将添加到my.cnf
:
general-log=1
general-log-file=/var/log/mysqlgeneral.log
然后sudo touch /var/log/mysqlgeneral.log
然后重启mysqld。注释掉上面的配置行并重新启动以关闭查询记录。