第二部分 进阶(Advanced)
1. Lattices
Lattice是一个创建并填充物化视图的框架,可以识别以及解决特定查询的物化视图。
一个Lattice代表一个星型(或雪花)模型,不是通用的schema。特别地,所有的连接关系必须是多对一,围绕星型模型的事实表建立。
Lattice的名字来源于数学: lattice是一个部分有序的集合,任何两个元素都有一个唯一的最大的下界和最小的上界。
[HRU96]发现,多维数据集可能的物化集合构成一个lattice,并且使用一种算法来选择一组较为优化的物化组合。Calcite的推荐算法也是源于此。
Lattice使用SQL statement来代表星型模型,以此来进行定义自身。SQL是一种有用的能表示多个table join关系的短语,并且可以为列名指定别名(与发明一种新的语言来表示关系,join 条件和基数相比,SQL表达更为方便)。
和常规sql不同,顺序在这里很重要。如果你在from模块中将A放在B前面,并且实现一个A和B的join关系,可以说是从A到B有一个多对一的关系。(例如,在lattice例子中,Sales事实表在时间维度表和产品维度表之前先被触发,产品维度表在产品分类维度表之前被触发,further down an arm of a snowflake.))
一个Lattice意味着一系列的约束。在A到B的关系中,A表上存在一个外键(例如,每一个A表中的外键都对应B表key中的一个值),和B表中的一个唯一key(例如,key值只会出现一次)。这些约束条件都非常重要,因为它允许计划器来移除没有用到的列的join关系,并且知道查询结果是不会改变的。
Calcite不会去校验约束条件,如果违反约束规则,Calcite会直接返回错误的结果。
Lattice是一个大的虚拟的join视图。它不是物化的(由于反规范化,它可能会比星型模型大好几倍),并且你可能并不想去对它进行查询(columns太多了)。所以它到底是干什么的呢?
1)如上面所说,lattice声明了许多有用的主键和外键的约束。
2)它帮助查询执行器将用户的查询行为映射到filter-join-aggregate 物化视图(针对DW查询最有用的物化视图类型)
3)给Calcite一个框架来收集关于数据卷和用户查询的统计信息
4)允许Calcite去自动设计和填充物化视图
大多数星型模型会强制用户去定义一个column到底是维度还是指标。在lattice中,每一个column都是维度列(也就是说,它可以成为GROUP BY子句中的一列,用于在特定维度上查询星型模式)。所有的column也同样可以用作度量(指标),你可以为指定列指定聚合函数来定义一个度量(指标)。
如果“unit_sales”通常更倾向于作为度量使用而不是维度,也没有影响。Calcite算法在不久的将来会注意到它很少被聚合,就不会倾向于在它上面创建聚合层(当前算法在设计tiles时不会参考查询历史)。
但有人或许想知道,少于5的订单和多于100的订单利润是会更多还是更少。在这种场景下,“unit_sales”突然就成为一个维度了。如果声明一个列为维度列的成本为0,我想我们应该让所有的列都成为维度列。
该模型允许一个指定表以不同的表别名被多次使用。可以在模型中定义OrderDate和ShipDate两个时间维度。
大多数SQL系统要求一个视图的中的列名是唯一的,在lattice中比较难达到,因为经常会在一次join中同时包含主键和外键列。因此,Calcite允许用户通过两种方式引用列,如果列是唯一的,可以直接使用它的名字【‘unit_sales’】。不管列在lattice是否唯一,它在自己的table中都是唯一的,因此你可以通过它的表名来对它进行引用。如下例
- [“sales”, “unit_sales”]
- [“ship_date”, “time_id”]
- [“order_date”, “time_id”]
一个“tile”是lattice中的一个带有一些特定维度(在Kylin中被称为cuboid——Cube则包含了所有维度的不同的两两组合,每一种组合即为一个Cuboid)的物化表。Lattice JSON元素中的tiles属性定义了一个初始的物化tile集合。
如果运行算法,可以省略tiles属性。Calcite会选择一个初始集合。如果定义了tiles属性,算法就会以定义的list开始启动运行,然后开始寻找其他互补的tiles(eg fill in the gaps left by the initail tiles)