sql – 为什么Slick在调用take()方法时会生成子查询
|
我用 Slick 1.0.0-RC1.我有这个表对象的定义: object ProductTable extends Table[(Int,String,Double,java.sql.Date,Int,Option[Int],Boolean)]("products") {
def id = column[Int]("productId",O.PrimaryKey,O.AutoInc)
def title = column[String]("title")
def description = column[String]("description")
def shortDescription = column[String]("shortDescription")
def price = column[Double]("price")
def addedDate = column[java.sql.Date]("addedDate")
def brandId = column[Int]("brandId")
def defaultImageId = column[Option[Int]]("defaultImageId")
def visitCounter = column[Int]("visitCounter")
def archived = column[Boolean]("archived")
def * = id ~ title ~ description ~ shortDescription ~ price ~ addedDate ~ brandId ~ defaultImageId ~ visitCounter ~ archived
}
我需要一个简单的查询,从数据库中选择8行: ProductTable.filter(_.title === "something") .sortBy(_.visitCounter) .map(_.title) .take(8) .selectStatement 输出是: select x2.x3 from
(select x4.`title` as x3 from `products` x4
where x4.`title` = 'something'
order by x4.`visitCounter` limit 8) x2
如果我摆脱了take()方法: ProductTable.filter(_.title === "something") .sortBy(_.visitCounter) .map(_.title) .selectStatement 然后输出是: select x2.`title` from `products` x2 where x2.`title` = 'something' order by x2.`visitCounter` 所以我的问题是:为什么Slick在使用take()方法构造查询对象时会生成子查询? 附:如果它可以相关,我使用MySql驱动程序与所有这些 解决方法有一个简短的答案和一个很长的答案.简短的一个是:子查询是存在的,因为到目前为止没有人愿意删除它.更长的答案与交换“map”和“take”没有任何区别的事实有关,这是由于查询的编译完全是简单和直接的. 在查询编译器的早期阶段,存在一个“forceOuterBinds”阶段,它引入(可能)许多额外的Bind(a.k.a. flatMap)操作,这些操作在语义上是等效的并且是冗余的.我们的想法是采用一些具有集合类型的x并将其转换为Bind(s,x,Pure(s)),其中s是一个新的符号.如果x已经是Pure(y)形状,我们将其转换为Bind(s,Pure(ProductNode()),Pure(y)).在Scala代码中,将此视为将x:List [T]转换为x.flatMap(s => List(s))或将List(y)转换为List(()).flatMap(s => List (Y)).此转换的目的是通过在我们可能想要执行此操作的所有位置为我们提供修改投影(作为标识映射创建)的位置,使后续编译器阶段中的树重写更容易. 稍后,在“convertToComprehensions”中,来自monadic形式的所有节点(Bind,Pure,Filter,Take,Drop等)将单独转换为Comprehension节点(表示SQL select语句).结果仍然不是合法的SQL:SQL理解不是monad理解.它们具有非常有限的范围规则,这些规则不允许from子句引用由前一个from子句引入的变量(在相同的理解或封闭的理解中). 这就是为什么我们需要下一个阶段“fuseComprehensions”,它可能看起来纯粹像乍看之下的优化,但实际上需要生成正确的代码.这个阶段试图尽可能地融合个人理解,以避免这些非法引用.我们已经取得了一些进展,我们可以融合但是100%的范围问题解决方案并不在眼前(事实上,我很确定无法解决). 重申一下,这一阶段的进展主要取决于对正确性的需求,而不仅仅是生成更好的代码.那么我们可以删除那个额外的子查询吗?是的,当然,但还没有人实现它. 如果您想尝试实现这样的优化,请注意以下几点: >您是否满足于删除纯粹的别名投影(即理解,其中选择槽的形式为Some(ProductNode(ch)),其中ch的每个元素都是Path)? (还有一些让我思考的问题:与解释为什么它还不存在相比,实施优化需要多长时间?) (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- sql-server – SQL Azure仅在sys.dm_exec_sessions中返回一
- sql-server-2008 – SQL Server存储过程行号问题
- MySQL动态字符串处理DYNAMIC_STRING
- sql-server – 如何查看当前的数据库邮件配置?
- SQL,计入多列然后分组
- sql – 这些数据库设计样式(或反模式)有名称吗?
- exception – 只有LINQ to Entities中的排序输入才支持’Sk
- MySQL5.6 Replication主从复制(读写分离) 配置完整版
- 如何在 SQL SERVER 中快速有条件删除海量数据
- SQL Server 数据库主键选取策略
