初探StarRocks V2.1.3之踩坑记录 原创

yadian
发布于 2022-6-2 09:44
浏览
1收藏

背景:当前项目中,数据部分整体采用Hive/SparkSQL+ES+HBase的架构,Hive/SparkSQL用于离线分析,ES+HBase用于实时查询。当业务规模不是那么庞大的时候,这套架构多少显得有点重。于是寻求一种轻量级解决方案,既满足离线分析的需求,又满足明细查询的需求。首先想到的是支持流批一体的MPP数据库,于是将目光锁定在了StarRocks、ClickHouse和TiDB这三款开源的MPP数据库上。

其中StarRocks和TiDB是国产开源,网上有博文说StarRocks和ClickHouse性能秒杀TiDB,因此首先将精力聚焦在StarRocks上面。且从开始预研最新版本V2.1.3到现在仅过去短短一个月时间,StarRocks官方已发布V2.2.0版本,中间还有V2.1.4、V2.1.5、V2.1.6三个小版本的发布。如此频繁的版本迭代,加上社区的高活跃度,StarRocks的未来还是值得期待的!

废话不多说,下面以流水账的形式记录此次StarRocks V2.1.3的踩坑过程。其中部分问题已在新版本中解决,部分可通过设计层面解决,部分仍需持续观察。


一、数据导入导出

A、Hive数据导入StarRocks

StarRocks支持Hive外表,可以建外表直连查询导入。

1、创建resource

create external resource hive0
properties (
  "type" = "hive",
  "hive.metastore.uris" = "thrift://tw01:9083"
);

2、创建外表

drop table if exists tmp.base_type;
create table tmp.base_type
(
    id bigint,
    type_name varchar(100)
) 
ENGINE=hive
PROPERTIES (
    "database" = "dwd",
    "table" = "base_type",
    "resource" = "hive0"
);

3、查询外表写入olap表

insert into dwd.base_type select * from tmp.base_type;

踩坑1:在此过程中,多张表数据顺利从Hive导入到StarRocks,但仍有两张表导入记录数为0。

而Hive表无论通过HiveServer2还是通过SparkThriftServer访问,都能正常查出数据。

经分析,顺利导入的表相应HDFS文件直接位于相应location目录下,未正常导入的表相应HDFS文件不是直接位于location目录下(location目录到数据文件中还有一层子目录)。

尝试将HDFS数据文件移动至location目录下后,外表正常查询到全部数据,问题得到解决!

(PS. SparkSQL也有类似情况,解决方案:将参数spark.hive.mapred.supports.subdirectories设置为true)

B、StarRocks数据导出到MySQL

StarRocks支持MySQL外表,既能通过外表读MySQL数据,也能通过外表往MySQL写数据。

踩坑2:在写入数据前,需要先清空目标表,因此想当然的对外表执行truncate操作。然而对MySQL外表的truncate操作并不被支持。若有该需求,还需在MySQL侧进行。


二、离线分析

1、对于大部分工作,基本上很难一条语句一步到位。对于复杂点的业务流程,甚至需要拆解成数十步完成,因此需要创建很多的临时表,即有很多的create table my_table_name as select语句。

踩坑3:select语句中出现子查询或者union all时,单独执行select查询没有问题,将查询结果insert into my_table_name也没有问题,但以查询结果create table my_table_name就会报错“unknown error”。期待新版本中解决此问题,或者使用者变通解决:在使用时先建表,再执行insert操作。

2、特定的业务场景,需要将同一分组下不同记录行的某个文本字段进行去重后拼接,且需要根据业务发生的时间进行排序(而非按照需要拼接的字段进行排序),如一个人的两个手机号按开户时间以逗号拼接成一个新字段。在使用SparkSQL时,可以将时间转换成出时间戳拼接在手机号前,再分组使用collect_list、sort_array、concat_ws,最后对时间戳部分内容进行替换,即可实现需求。

regexp_replace(concat_ws(',', sort_array(collect_list(concat_ws(':', cast(unix_timestamp(net_tm) as string), phone_no)))), '\\d+\:','')

踩坑4:在StarRocks V2.1.3中,可用group_concat实现拼接,但无法排序。根据官方论坛中的讨论,V2.2版本将支持去重排序后拼接(详见https://forum.starrocks.com/t/topic/1023),即

array_join(array_sort(array_distinct(array_agg(c1)), ','))

目前V2.2版本已发布,该功能点待验证。

3、对于数据仓库,调度的周期是固定的,每次跑数的时间区间也是固定的。但某些业务场景,不同于传统数据仓库,需要手工干预且设定可变跑数时间区间,如20220101到20220110,或20220101到20220131。而为防止重复写入数据,需要预先清除目标分区。对于Hive&SparkSQL而言,使用insert overwrite table直接覆盖目标分区,无需预先清除目标分区。对于StarRocks而言,就需要先执行truncate table table_name partition(p1, p2, p3),再执行insert语句。

踩坑5:在StarRocks中,对表truncate分区,分区数量可变,但必须全部指定。对于这种可变区间的做法,就需要变通解决:通过额外程序实现,或在跑数前手工指定目标分区进行truncate操作。

PS.根据论坛中官方的回复https://forum.starrocks.com/t/topic/2138,已在github上提相应需求(详见链接https://github.com/StarRocks/starrocks/issues/5387),期待后续版本中实现该功能。

4、对于周末加班和节假日加班,工资需要按2倍、3倍进行发放。

对Hive&SparkSQL而言,设计一张表base_holiday(start_time string, end_time string, multiple int),每一次N天假期,维护一条配置记录即可。计算假期加班工资,只需要关联该表,要求上班日期 between start_time and end_time即可。

踩坑6:以上做法在StarRocks中执行报错,提示不支持非等值关联。非等值关联,意味着笛卡尔积,对很多经验不足的人来说,使用就会带来灾难。

这时候,只能变通解决。改变base_holiday的设计,枚举所有的假期日期。如

start_time end_time multiple
2022-04-30 00:00:00 2022-05-04 23:59:59 3

改成

holiday_date multiple
2022-04-30 3
2022-05-01 3
2022-05-02 3
2022-05-03 3
2022-05-04 3

这时,关联该表,取上班日期等于holiday_date即可。

5、某些业务场景下,需要根据特定字段对数据进行分档分级。在Hive&SparkSQL中,ntile(10)over(order by xxx desc) 即可实现该需求。

踩坑7:StarRocks暂不支持该函数。

一个月前在官方论坛中询问后续是否会提供该函数,今天看到github上已经有将该函数纳入V2.3版本的计划(详见https://github.com/StarRocks/docs.zh-cn/pull/620)。

6、某些业务场景下,需要的功能点无法通过SQL实现,而需要借助UDF,最普遍的是用java实现UDF。如计算两个字符串之间的最小编辑距离等。

踩坑8:StarRocksV2.1暂不支持Java UDF,今天看到官网的公告中V2.2已经支持Java UDF,目前正公测中,我们原有的Hive UDF功能待移植验证。


三、实时查询

功能层面,筛选条件转换成查询语句中的where条件即可,任意一款数据库均能实现,关键在于性能方面能否满足要求,返回查询结果不说毫秒内完成,起码不能超过1秒钟。

StarRocks的前缀索引暂未深入研究,仅采用业务日期分区并对关键过滤字段创建bitmap索引,180个字段日增量800万数据的表,常用字段不到20个,对于80%以上的查询,平均耗时完全可以控制在0.8秒以内。

理论上,正确合理的利用前缀索引、bitmap索引、Bloomfilter索引,以及分区键、分桶键等,查询效率能够大幅提升,对于一般的系统来说,StarRocks完全能够胜任。

踩坑9:曾经使用MySQL、Oracle和DB2等创建索引时就有一个等待过程的心理预期,但在StarRocks创建bitmap索引的过程中,create index语句瞬间执行完成,不免惊讶,这也太快了吧!实际上,这时候查询,索引并不能起到作用,因为StarRocks创建索引是异步操作,create index语句执行完后,索引的创建过程仍在后台执行。创建索引的状态,可以通过以下语句查询。

show alter table column where tablename = 'my_table_name';

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
分类
2
收藏 1
回复
举报
回复
    相关推荐