目前业务在使用Kylin的时候反馈查询很慢,直接超时了(超时时间设置的为5min),在日志中获取了相应的SQL以及Cube之后发现:
- SQL扫描了不到2个月的数据,500多G大小,26亿的记录数;
- SQL中涉及到了4个count distinct计算(bitmap);
当前集群环境如下:
- Kylin服务器2台,部署了2个节点,都是all;
- HBase集群服务器4台,每台部署了2个regionserver;
- Kylin版本为2.6.6;
该cube设置的合并时间为7天/28天,Storage情况如下所示:
- 有一个时间跨度为1个月的segment,大小270G,region数量为10;
- 有两个时间跨度为1周的segment,大小为90G,region数量为10;
- 若干个时间跨度为1天的segment,大小为13G,region数量为4个,记录数大概是7000W;
初步猜测是因为扫描的数据太多了,而且涉及到多个count distinct的计算,所以比较耗时。而且在执行SQL的过程中,我们发现HBase集群的CPU也没有明显的飙升。首先怀疑是因为region数量设置的太少,导致并发度不够,因此CPU没有完全利用起来,当前设置的最大region数量是10。为了进行验证,我们在这个cube上配置最大region数量为50,然后refresh了其中一个1周的数据,refresh前后对比如下:
操作 | segment | region个数 | 查询时间 |
---|---|---|---|
刷新前 | [20200801,20200808) | 10 | 37.11/35.69/36.33/36.25/35.84 |
刷新后 | [20200801,20200808) | 25 | 37.36/36.18/36.93/35.74/35.45 |
我们可以发现,即使segment对应的HBase表的region数量增多了,对于查询也并没有提升。我们通过仔细查看上述SQL的相关日志发现如下所示的情况:
由于我们测试时候只查询了1周的数据,也只有1个segment,所以我们在日志中发现,只有1个request发送到了1个regionserver上,结合Kylin的coprocessor相关代码(相关代码位于CubeHBaseEndpointRPC.java,有兴趣的可以自行阅读),我们发现:Kylin中的一个hbase表(即一个segment)对应一个coprocessor,查询过程中会先发送一个request到一个segionserver上,然后该HBase会把该表的数据都拉到这个regionserver上,使用coprocessor进行聚合运算。基于这个情况,我们目前判断应该是segment越多的情况下,扫描会越快。因此我们又进行了下述的测试,相关信息如下:
segment区间 | segment数量 | region个数 | 查询时间 |
---|---|---|---|
[20200801,20200806) | 1 | 25 | 27.27/26.46/25.44/24.97/24.88 |
[20200816,20200821) | 5 | 5*4 | 6.77/6.47/6.34/6.55/6.43 |
我们可以看到,查询同样5天的数据,5个segment的情况,比1个segment的情况,查询性能好了4倍以上。这也证实了我们上面的结论。到这里,我们这个问题就已经排查的差不多了。 针对这个问题,我们进行了如下的调整:
- Clone该cube,然后新的cube去掉segment的合并配置,用新的cube跑完数据之后,disable掉老的cube,需要指的注意的是,两个cube涉及到的表都是一样的,查询的时候可能会路由到不同的cube;
- 由于当前还是只查询了1周的数据,未来的查询时间跨度可能更长,因此我们准备对HBase进行相应的扩容。