优化 Slick 生成的 SQL 查询

Posted

技术标签:

【中文标题】优化 Slick 生成的 SQL 查询【英文标题】:Optimizing Slick generated SQL query 【发布时间】:2015-11-08 13:21:03 【问题描述】:

我有一个非常简单的查询,SQL 可以表示如下:

SELECT
  c.id,
  count(cp.product_id)
FROM cart c LEFT OUTER JOIN cart_product cp ON c.id = cp.cart_id
WHERE c.id = 3
GROUP BY c.id;

当使用Slick DSL 表示上面的查询时,我感到非常惊讶,查询是从以下DSL 生成的:

Cart.joinLeft(CartProduct)
  .on  case (c, cp) => c.id === cp.cartId 
  .filter  case (c, cp) => c.id === 3 
  .groupBy  case (c, cp) => c.id 
  .map  case (c, pr) => (c, pr.length)

如下图:

SELECT
  x2.x3,
  count(1)
FROM (SELECT
        x4.x5  AS x3,
        x4.x6  AS x7,
        x8.x9  AS x10,
        x8.x11 AS x12,
        x8.x13 AS x14,
        x8.x15 AS x16
      FROM (SELECT
              x17."id"      AS x5,
              x17."user_id" AS x6
            FROM "cart" x17) x4 LEFT OUTER JOIN (SELECT
                                                   1                AS x9,
                                                   x18."id"         AS x11,
                                                   x18."cart_id"    AS x13,
                                                   x18."product_id" AS x15
                                                 FROM "cart_product" x18) x8 ON x4.x5 = x8.x13) x2
WHERE x2.x3 = 3
GROUP BY x2.x3;

我做错了什么?看到这样的嵌套查询是否正常?如果查询的复杂性增长得如此之快,那么使用 Slick DSL 有什么意义呢?我可能会写原生的SQL,但我真的很喜欢Slick DSL。优化Slick查询的技巧有哪些?

【问题讨论】:

我没有尝试过这个特定的版本,但可能是 3.1.0-M2 有助于避免子查询。 slick.typesafe.com/news/2015/08/13/slick-3.1.0-M2-released.html。里程碑发布的主要亮点“新的查询编译器后端。主要目标是尽可能避免子查询。当前版本功能齐全。” 谢谢,我会试一试,我会尽快更新。 如果您使用的是 mysql,那么这是一个已知问题。 github.com/slick/slick/issues/489。 Slick-3.1.0 应该会产生更好的查询。 很遗憾没有,我用的是PostgreSQL 删除连接部分并执行如下查询会发生什么情况:SELECT cp.cart_id, count(cp.product_id) FROM cart_product cp WHERE cp.cart_id = 3 GROUP BY cp.cart_id; 它会改变执行计划吗? 【参考方案1】:

既然你已经写了你正在使用 PostgreSQL,那么我不会担心,因为 PostgreSQL 以一个非常好的查询优化器而闻名。如此简单的转换毫不费力,几乎不需要额外的时间。唯一要做的就是等待,问题最终会在上游(Slick 版本 3.1 左右)得到解决,而您无需执行任何操作。

ps:你为什么不简单地使用这个查询?如果表上有外部约束,它应该返回完全相同的结果:

SELECT id, COUNT(*) FROM cart_product WHERE id=3

【讨论】:

希望3.1 能够修复查询嵌套问题。

以上是关于优化 Slick 生成的 SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章

slick for play 使用原生sql查询以及拼接sql

如何在 slick 中使用 sql""" 插值编写动态 SQL 查询

Slick教程

从 SQL Server 查询优化器生成多个脚本

查询优化怎样用SQL语句查看查询的性能指标

MySQL优化--02----慢SQL定位慢查询日志