kylin-rowkey 编码

在Rowkeys设置区域中,每个维度都有几项关键的配置

编码:代表了该维度的值应使用何种方式进行编码,合适的编码能够减少维度对空间的占用,例如,我们可以把所有的日期都用三个字节进行编码,相比于字符串存储,或者是使用长整数形式存储的方法,我们的编码方式能够大大减少每行Cube数据的体积。而Cube中可能存在数以亿计的行数,使用编码节约的空间累加起来将是一个非常巨大的数字。

目前Kylin支持的编码方式有以下几种。

·Date编码:将日期类型的数据使用三个字节进行编码,其支持从0000-01-01到9999-01-01中的每一个日期。

·Time编码:仅支持表示从1970-01-0100:00:00到2038-01-1903:14:07的时间,且Time-stamp类型的维度经过编码和反编码之后,会失去毫秒信息,所以说Time编码仅仅支持到秒。但是Time编码的优势是每个维度仅仅使用4个字节,这相比普通的长整数编码节约了一半。如果能够接受秒级的时间精度,请选择Time编码来代表时间的维度。

·Integer编码:Integer编码需要提供一个额外的参数“Length”来代表需要多少个字节。Length的长度为1~8。如果用来编码int32类型的整数,可以将Length设为4;如果用来编码int64类型的整数,可以将Length设为8。在更多情况下,如果知道一个整数类型维度的可能值都很小,那么就能使用Length为2甚至是1的int编码来存储,这将能够有效避免存储空间的浪费。

·Dict编码:对于使用该种编码的维度,每个Segment在构建的时候都会为这个维度所有可能的值创建一个字典,然后使用字典中每个值的编号来编码。Dict的优势是产生的编码非常紧凑,尤其在维度值的基数较小且长度较大的情况下,特别节约空间。由于产生的字典是在查询时加载入构建引擎和查询引擎的,所以在维度的基数大、长度也大的情况下,容易造成构建引擎或查询引擎的内存溢出。

·Fixed_length编码:编码需要提供一个额外的参数“Length”来代表需要多少个字节。该编码可以看作Dict编码的一种补充。对于基数大、长度也大的维度来说,使用Dict可能不能正常工作,于是可以采用一段固定长度的字节来存储代表维度值的字节数组,该数组为字符串形式的维度值的UTF-8字节。如果维度值的长度大于预设的Length,那么超出的部分将会被截断。

维度分片(Shard by Dimension):默认情况下系统可能会对Cuboid的数据进行分片处理,Cuboid的分片策略是随机的,也就是说,我们无法控制Cuboid的哪些行会被分到同一个分片中。这种默认的方法固然能够提高读取的并发程度,但是它仍然有优化的空间。按维度分片(Shard by Dimension)提供了一种更加高效的分片策略,那就是按照某个特定维度进行分片。简单地说,如果Cuboid中某两个行的Shard by Dimension的值相同,那么无论这个Cuboid最终会被划分成多少个分片,这两行数据必然会被分配到同一个分片中。

这种分片策略对查询有着极大的好处。我们知道,Cuboid的每个分片都会被分配到存储引擎的不同物理机器上。Kylin在读取Cuboid数据的时候会向存储引擎的若干机器发送所读取的RPC请求。在RPC请求接收端,存储引擎会读取本机的分片数据,并在进行一定的预处理后再发送RPC回应。以HBase存储引擎为例,不同的Region代表不同的Cuboid分片,在读取Cuboid数据的时候,HBase会为每个Region开启一个Coprocessor实例来处理查询引擎的请求。查询引擎将查询条件和分组条件作为请求参数的一部分发送到Coprocessor中,Coprocessor就能够在返回结果之前先对当前分片的数据做一定的预聚合(这里的预聚合不是Cube构建的预聚合,而是针对特定查询深度的预聚合)。

如果按照维度划分分片,假设按照一个基数比较高的维度seller_id进行分片,那么在这种情况下,每个分片将会承担一部分的seller_id,且各个分片不会有相同的seller_id。所有按照seller_id分组(Group byseller_id)的查询都会变得更加高效,因为每个分区预聚合的结果都会更加专注于某一些seller_id之上,使得分片返回的结果数量大大减少,查询引擎端也无需对各个分片的结果做分片间的聚合。按维度分片也能让过滤条件的执行更加高效,因为是按维度分片,所以每个分片的数据都会更加“整洁”,更方便查找和索引。

调整Rowkeys顺序同样可以优化我们的查询。

在上图中,我们可以上下拖动每一个维度来调节维度在Rowkeys中的顺序。这种顺序对于查询非常重要,因为在目前的实现中,Kylin会把所有的维度按照顺序黏合成一个完整的Rowkeys,并且按照这个Rowkeys升序排列Cuboid中所有的行。

所以,在调整Rowkeys的顺序时需要遵守以下几个原则:

在查询中被用作过滤条件的维度有可能放在其他维度的前面。

将经常出现在查询中的维度放在不经常出现的维度的前面。

对于基数较高的维度,如果查询会有这个维度上的过滤条件,那么将它往前调整;如果没有,则向后调整。

你可能感兴趣的:(kylin-rowkey 编码)