Slick 中的典型表现(ver. 3.1.1)

Typical performance in Slick (ver. 3.1.1)

我有以下 SQL 查询:

select `sr_roleName`, `sr_id` from `db_security_role` where `sr_roleName` = 'admin'

它是从以下 Slick 代码生成的:

RoleTable.filter(_.name === roleName).result.head

所以 - 它看起来很简单(实际上是您可能拥有的最简单的东西,对吧?)。现在让我们看看以下结果(下面的日志):

[debug] s.c.QueryCompilerBenchmark - ------------------- Phase: Time ---------
[debug] s.c.QueryCompilerBenchmark -       assignUniqueSymbols:    0.257579 ms
[debug] s.c.QueryCompilerBenchmark -                inferTypes:    0.774230 ms
[debug] s.c.QueryCompilerBenchmark -              expandTables:   18.949290 ms
[debug] s.c.QueryCompilerBenchmark -           forceOuterBinds:    3.438698 ms
[debug] s.c.QueryCompilerBenchmark -         removeMappedTypes:    2.760705 ms
[debug] s.c.QueryCompilerBenchmark -                expandSums:    0.702326 ms
[debug] s.c.QueryCompilerBenchmark -         emulateOuterJoins:    1.025963 ms
[debug] s.c.QueryCompilerBenchmark -             expandRecords:    1.022323 ms
[debug] s.c.QueryCompilerBenchmark -        flattenProjections:   10.691557 ms
[debug] s.c.QueryCompilerBenchmark -              rewriteJoins:    0.790561 ms
[debug] s.c.QueryCompilerBenchmark -             verifySymbols:    4.421257 ms
[debug] s.c.QueryCompilerBenchmark -             relabelUnions:    1.511849 ms
[debug] s.c.QueryCompilerBenchmark -          createAggregates:    0.612787 ms
[debug] s.c.QueryCompilerBenchmark -           resolveZipJoins:    0.723972 ms
[debug] s.c.QueryCompilerBenchmark -          pruneProjections:    4.261886 ms
[debug] s.c.QueryCompilerBenchmark -           rewriteDistinct:    2.408857 ms
[debug] s.c.QueryCompilerBenchmark -    createResultSetMapping:    2.745822 ms
[debug] s.c.QueryCompilerBenchmark -            hoistClientOps:    7.755399 ms
[debug] s.c.QueryCompilerBenchmark -         reorderOperations:    1.650360 ms
[debug] s.c.QueryCompilerBenchmark -     mergeToComprehensions:   27.408578 ms
[debug] s.c.QueryCompilerBenchmark -            optimizeScalar:    1.784032 ms
[debug] s.c.QueryCompilerBenchmark -          removeFieldNames:   13.811206 ms
[debug] s.c.QueryCompilerBenchmark -                   codeGen:   20.328294 ms
[debug] s.c.QueryCompilerBenchmark -                     TOTAL:  129.837531 ms
[debug] s.j.J.statement - Preparing statement: select `sr_roleName`, `sr_id` from `db_security_role` where `sr_roleName` = 'admin'
[debug] s.j.J.benchmark - Execution of prepared statement took 425µs

如您所见,实际查询执行成本(耗时)约为 425µs。可能 - 它在本地机器/本地数据库上执行。然而对我来说极其奇怪的是:整个查询准备时间总共花费了 129.837531 毫秒(这是实际查询执行时间的 300 倍)。

基本上我的问题是:

谢谢

好像有道理。每次执行参数化查询时,slick 都需要重新编译它。这可以通过预编译此类查询来避免。例如:

def findByRoleName(roleName: Rep[String]) = RoleTable.filter(_.name === roleName)

val findByRoleNameCompiled = Compiled(findByRoleName _)

val result = findByRoleNameCompiled("myRole").result.head

现在查询将只编译一次,您应该会注意到性能有所提高。这也适用于插入、更新和删除。有关详细信息,请参阅文档中的 Compiled Queries

实际上正确答案在@szeiger 的评论中:

查询准备时间长只是由于 JVM 未预热造成的。多次执行各种查询后,下一个查询准备得更快。还值得记住@Roman 指出的查询编译(尽管这并不是问题本质的全部内容)。

@szeiger 在上述评论中的引用基本上是对这个问题的最佳答案:

Averaged over 53 queries of low to medium complexity, I get 183 ms for the first run and only 14 ms after a few dozen runs