美文网首页
kylin-Cube中的Rowkey优化

kylin-Cube中的Rowkey优化

作者: 李小李的路 | 来源:发表于2020-02-23 17:46 被阅读0次
  • 基于kylin-3.0
  • 重点通过对Cube的Rowkey的设置来优化Cube的查询性能

前言

  • Cube的每个Cuboid中包含大量的行,每个行又分为Rowkey和Measuer两个部分。每行Cuboid数据中Rowkey都包含当前Cuboid中所有维度的值的组合。Rowkey中的各个维度按照Cube Designer --> Advanced Setting --> RowKeys中设置的顺序和编码进行组织,如下图所示:


    Rowkey
  • 在Rowkeys 设置页面中,每个维度都有几项关键的配置。下面将一一到来。

调整Rowkey顺序

  • 在Cube Designer --> Advanced Setting --> Rowkeys部分,可以上下拖动每一个维度来调节在Rowkey中的顺序。这种顺序对应查询非常重要,因为目前在实现中,kylin会把所有的维度按照显示顺序粘合成一个完整的Rowkey,并且按照这个Rowkey升序排列Cuboid中所有的行,参照上图。
  • 不难发现,对排序考前的维度进行过滤的效果会非常好,比如在上图中的Cuboid,如果对D1进行过滤,它是严格按照顺序进行排列的;如果对D3进行过滤,它仅是在D1相同时在组内顺序排列。
  • 如果在一个比较考后的维度进行过滤,那么这个过滤的执行就会非常复杂。以目前的HBase存储引擎为例,Cube的Rowkey就对应HBase中的Rowkey,是一段字节数组。我们目前还有创建单独的每个维度的倒排索引,因此对于在比较靠后的维度上的过滤条件,只能依靠HBase的Fuzzy Key Filter来执行。尽管HBase做了大量的相应优化,但是在对靠后的字节运行Fuzzy Key Filter时,一旦前面维度的基数很大,Fuzzy Key Filter的寻找代价就会很高,执行效率就会降低。所以在调整Rowkey的顺序时需要遵守以下几个原则:
  • 有可能在查询中被用作过滤条件的维度,应当放在其他维度的前面。
    • 对于多个可能用作过滤条件的维度,基数高的(意味着用它进行过滤时,较多的行过滤,返回的结果集较小)更适合放在前面;
    • 总体而言,可以用下面的这个公司为维度打分,得分越高的维度越应该放在前排:排序评分=维度出现在过滤条件中的概率 * 用该维度进行过滤时就可以过滤掉的记录数;
  • 将经常出现在查询中的维度,放在不经常出现的维度的前面,这样,在需要进行后聚合的场景中查询效率会更高。
  • 对于不会出现在过滤条件中的维度,按照其基数的高低,优先将低基数的维度放在Rowkey的后面。这是因为在逐层构建Cuboid、确定Cuboid生成树时,Kylin会优先选择Rowkey后面的维度所在的父Cuboid来生成子Cuboid,那么基数越低的维度,包含它的父Cuboid的行数越少,聚合生成子Cuboid的代价就越小。

选择合适的维度编码

  • Apache Kylin支持多种维度编码方式,用户可以针对数据特征,选择合适的编码方式,从而减小数据的存储空间。在具体的使用过程中,如果用错了编码方式,可能会导致构建和查询的一系列问题。
  • 详见 kyin-Cube中对Rowkey的编码方式

按维度分片

  • kylin-Cube查询并发粒度优化中介绍过,系统会对Cuboid中的数据在存储时进行分片处理。默认情况下,Cuboid的分片策略是对于所有列进行哈希计算后随机分配的。也就是说,我们无法控制Cuboid的哪些行会被分到同一个分片中。这种默认的方法固然能够提高读取的并发度,但是它仍有优化的空间。按维度分片提供了一种更加高效的分片策略,那就是按照某个特定维度进行分片(Shard By Dimension)。简单的说,当你选取了一个维度用于分片后,如果Cuboid中的某两行在该维度上的值相同,那么无论这个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 by seller_id)的查询都会变得更加高效,因为每个分片预聚合的结果会更加专注于某些seller_id,使得分片返回结果的数量大大减少,查询引擎端也无需对各个分片的结果做分片间的聚合。按维度分片也能让过滤条件的执行更加高效,因为由于按维度分片,每个分片的数据都更加“整洁”,便于查找和索引。

相关文章

网友评论

      本文标题:kylin-Cube中的Rowkey优化

      本文链接:https://www.haomeiwen.com/subject/wnzdqhtx.html