有一个简短的答案,一个很长的答案。简短的是:子查询在那里,因为到目前为止没有人费心删除它。
更长的答案与以下事实有关:交换“ map”和“ take”没有任何区别,这是由于查询的编译非常简单明了。
相对早于查询编译器,存在一个“ forceOuterBinds”阶段,该阶段(潜在地)引入了许多额外的Bind(aka
flatMap)操作,这些操作在语义上是等效的和冗余的。想法是取一些具有集合类型的 x 并将其转换为 Bind(s,x,Pure(s)) ,其中
s 是新鲜的Symbol。如果 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”,从一元形式(绑定,纯净,过滤,冒,滴等)的所有节点都转换 单独 修真节点(代表SQL
选择 语句)。结果仍然不是合法的SQL:SQL理解不是monad理解。它们具有非常有限的作用域规则,不允许 from 子句引用由先前的 from
子句引入的变量(在同一理解或封闭理解中)。
这就是为什么我们需要下一个阶段“
fuseComprehensions”,乍一看似乎完全是一个优化,但实际上是生成正确代码所必需的。此阶段尝试尽可能地融合个人理解,以避免这些非法引用。我们在融合方面取得了一些进展,但是并没有100%解决示波器问题的方法(实际上,我很确定这是不可能解决的)。
重申一下,此阶段的进展主要是由对 正确性 的需求驱动的,而不仅仅是生成更好的代码。那么我们可以删除多余的子查询吗?是的,当然可以,但是还没有人实施。
如果您想尝试实现这种优化,请考虑以下注意事项:
- 您是否满足于删除纯粹的混叠投影(即, 选择 槽具有Some(ProductNode(ch))形式(其中ch的每个元素都是路径)的理解)?
- 或者,也许您认为还应该融合 从(… limit …)) 中 选择x + 1的方法 。您可以使用哪种表达方式?例如,RowNum可以吗?
- 子查询需要什么样的形状?例如,它可以包含 groupBy 或 orderBy 子句吗?
(还有一些我要考虑的问题:与解释为什么尚不存在优化相比,实现该优化需要花费多长时间?)



