润乾公司开源了一个前端BI系统,它在技术层面提出了一个别致的DQL(Dimentional Query Language)语言。具体介绍可以参考乾学院的文章
润乾的观点是终端用户难以理解复杂的SQL JOIN,为了便于多维分析,只能使用大宽表,这为数据准备带来一系列困难。而DQL则是简化了对终端用户而言JOIN操作的心智模型,并且在性能上相比于SQL更有优势。
以如何查找中国经理的美国员工为例
|
这里的关键点被称为:外键属性化,也就是说外键指向表的字段可直接用子属性的方式引用,也允许多层和递归引用。
另一个类似的例子是根据订单表 (orders),区域表(area),查询订单的发货城市名称、以及所在的省份名称、地区名称。
|
DQL的第二个关键思想是:同维表等同化,也就是一对一关联的表,不用明确写关联查询条件,可以认为它们的字段是共享的。例如,员工表和经理表是一对一的,我们需要查询所有员工的收入
|
DQL的第三个关键思想是:子表集合化,例如订单明细表可以看作是订单表的一个集合字段。如果要计算每张订单的汇总金额,
|
“如果有多个子表时,SQL 需要分别先做 GROUP, 然后在一起和主表 JOIN 才行,会写成子查询的形式,但是 DQL 则仍然很简单,SELECT 后直接再加字段就可以了”。
DQL的第四个关键思想是:数据按维度自然对齐。我们不用特意指定关联条件,最终数据之所以能够放在同一张表里展示,原因不是因为它们之间存在什么先验的关联关系,仅仅是因为它们共享了最左侧的维度坐标而已。例如:我们希望按日期统计合同额、回款额和库存金额。我们需要从三个表分别取数据,然后按照日期对齐,汇总到结果数据集中。
|
在 DQL 中,维度对齐可以和外键属性化结合,例如
|
如果从NopOrm的角度去看DQL的设计,则显然DQL本质上也是一种ORM的设计。
DQL需要通过设计器定义主外键关联,并为每个字段指定界面上的显式名称,这一做法完全与ORM模型设计相同。
DQL的外键属性化、同维等同化和子表集合化本质上就是EQL语法中的对象属性关联语法,只是它直接用数据库的关联字段作为关联对象名。这种做法比较简单,但缺点是对于复合主键关联的情况不太好处理。
DQL的维度对齐是一个有趣的思想。它的具体实现应该是分多个SQL语句去加载数据,然后在内存中通过Hash Join来实现关联,速度很快。特别是在分页查询的情况下,我们可以只对主表进行分页查询,然后其他子表通过in条件只取本页数据涉及到的记录即可,在大表的情况下有可能加速很多。
Nop平台中的MdxQueryExecutor实现了类似DQL的维度对齐查询。因为EQL已经内置支持了对象属性关联,所以只要实现对QueryBean对象的拆分、分片执行、数据并置融合就可以了。
MdxQueryExecutor的执行逻辑
- 拆分出主表字段和关联子表字段
- 如果主表字段包含汇总自动,则非汇总的字段自动被加入group by部分,并成为dimFields。查询子表的时候会取主表dimFields对应的结果,然后作为filter过滤子表数据
- 求取主表的dimFields和关联子表的关联字段的交集,则成为子表的dimFields。取交集是因为主表中的关联字段可能被汇总掉了,从而不是最终的dimFields的一部分。dimFields必须在选择列表中,因为最后需要利用这些字段进行关联。
- 如果是一对多关联,则dimFields全部加入group by