同时满足实时及离线数据分析需求!京东到家的StarRocks应用实践
The following article is from 达达集团技术 Author 李德宏
京东到家是达达集团旗下中国领先的本地即时零售平台,依托达达快送和零售合作伙伴,为消费者提供超市便利、生鲜果蔬、医药健康、3C 家电、鲜花绿植、蛋糕美食、服饰运动、家居时尚、个护美妆等海量商品约1小时配送到家的即时消费服务体验。海博系统是京东到家基于多年深耕零售 O2O 以及服务众多零售企业数字化转型的经验,自主研发的集商品、用户、营销、履约、数据五大数字化赋能模块于一体的全渠道数字化解决方案。
“ 作者:李德宏,
京东到家大数据开发工程师 ”
业务现状
海博系统建设了全渠道全业态融合的数据中台,可以同时满足实时及离线数据分析需求,提供可配置的数据看板功能,能有效提升商家运营效率,助力商家线上业务增长。海博数据中台目前支撑了超百亿级数据的统计分析,包括销售、运营、品类、履约等多主题经营分析数据报表70+, 涵盖了商家、门店、渠道、省、市等多维度分析指标350+。
平台数据量大,根据源表数据计算,数据中台日增数据量在数亿级别;查询分析维度多,以商品分析为例,查询维度包括省、市、商家、门店、渠道、品牌、子品牌以及不同时间范围的组合,组合后查询维度高达上百种;准实时数据推送频率高:数据中台的实时数据是以微批方式处理,窗口时间为10分钟,这样每天会有大量的准实时数据推送任务要执行,对数据存储引擎的实时导入性能要求较高。
商品、库存、订单等系统产生的源数据信息落库在 MySQL,经由数仓抽数后进行一系列加工处理,将计算好的结构化数据存储在统一的数据仓库中,根据数据的特点,我们使用了 MySQL 和 StarRocks 数据库并存的方式进行数据存储。集群会根据数据的不同特征采取不同的推送方式,实时数据使用 stream load、离线数据使用 broker load,结合我们自研的调度平台等多种方式进行数据推送, StarRocks 现阶段存储数据量整体占比估算为80%+,未来 StarRocks 也会作为我们数据应用层最主要的存储引擎,将充分利用 StarRocks 的向量化及物化视图等技术,支撑数据中台数据量的快速增长。
StarRocks 实践经验
遇到的挑战及解决方案
StarRocks 是面向列式存储的分布式架构,虽然兼容 MySQL 协议,但是与 MySQL 也有一些不同的特性。数据中台是首次接入 StarRocks,不可避免的,在实际开发过程中我们也踩到了一些坑。下面是我们遇到的问题汇总及解决方案:
1 分页查询使用不同的排序列,导致查询结果不一致问题
CREATE TABLE `api_hw_prd_sku_brand_sku_di` (
`create_date` date NOT NULL COMMENT "日",
`upc` VARCHAR ( 255 ) NOT NULL COMMENT "upc",
`stk_avl_cnt` BIGINT ( 20 ) NOT NULL COMMENT "",
...
) ENGINE = OLAP
DUPLICATE KEY (`create_date` )
COMMENT "商品表"
PARTITION BY RANGE ( `create_date` ) (PARTITION p20200726 VALUES [ ( '2020-07-26' ), ( '2020-07-27' ) ) ) DISTRIBUTED BY HASH ( `brand_trademark_id`, `vender_id` ) BUCKETS 10 PROPERTIES (
"replication_num" = "3",
...
);
分页查询语句1,使用 upc 列进行排序:
select stk_avl_cnt from api_hw_prd_sku_brand_sku_di
where create_date = ‘xx’order by upc desc limit ‘xx’,‘xx’
select stk_avl_cnt from api_hw_prd_sku_brand_sku_di
where create_date = ‘xx’order by create_date desc limit ‘xx’,‘xx’
为了验证问题,我们把查询的结果进行累加。以下为4次测试的结果:
从结果中可以看到,order by UPC 排序后累加的结果是一致的,4次结果都是19908,order by create_date 每次的结果都不相同21663,19344,18457, 15856,那么是什么原因导致的使用 order by create_date 排序,每次查询结果都有差异呢?
解决方案:提高 order by 后指定列的区分度,在建表时我们新增了一个类似 MySQL 中 id 特性的字段,在分页查询时,除指定业务需要排序的列以外,另加上此 id 列,保证查询的数据整体是有序的。
2 一条 SQL 中包含多个 case when 语句,导致执行耗时长问题
在执行计划中可以看到 SQL 耗时为 4s468ms,性能非常低,是不可以接受的。分析原因是 SQL 中包含多个 case when 语句,数据要从表中查询出来,在通过 case when 指定的条件进行过滤,在分布式的场景下,数据在多机之间传递,非常消耗性能。
以下是通过 StarRocks 提供的 Profile 工具分析出的优化后 SQL 执行耗时情况:
拆分后的 SQL 并行执行最长的为 248ms ,性能提高了 18 倍。
CREATE TABLE `sku_and_attribute_info` (
...,
`upc` VARCHAR(255) NOT NULL COMMENT “upc”,
`attribute_info` ARRAY<VARCHAR(1000)> NOT NULL COMMENT “商品属性信息”,
...
) ENGINE = OLAP
SELECT s.* FROM api_hw_prd_sku_brand_sku_di s
INNER JOIN sku_and_attribute_info a on s.upc = a.upc and array_contains(a.attribute_info, 'xxx') = 1
WHERE s.upc = 6903148044698
ORDER BY s.upc
LIMIT 0,10
用例 1 :
用例 2 :
从以上2个结果可以看出,用例2的结果与源数据是不一致的。那么问题出在哪里呢?
1、SQL 中包含 group by 语句时,group by 指定列不参加聚合操作,select 中的其他列都要指定聚合函数。
正确示例:
select a, max(b), max(c) from tx group by a
错误示例:
select a, b, c from tx group by a
以上示例中,select 查询的 b 和 c 列没有参与到 group by 分组中,所以查询时必须要指定聚合函数。
2、SQL 中包含 limit 语句,当从查询第二页开始,limit 后要加 order by 排序列,排序列区分度一定要高,否则一条数据可能会被重复查出。
正确示例:
select id , b, c from tx limit 10, 10 order by id desc
错误示例:
select id , b, c from tx limit 10, 10
未来工作
为更好地满足用户的多维分析场景,提高数据的查询效率,用数据驱动业务,在未来使用 StarRocks 过程中,主要的方向有以下几点:
通过对用户的行为分析,统计出报表高频的查询场景,使用物化视图进行数据的预聚合,进一步提升查询性能。
对于商品、订单等单维度聚合统计类型的报表,这类报表维度相对固定,并且没有查询明细数据的需求,因而可以采用聚合模型来替代明细模型,这样不仅可以提升聚合查询性能,也能减少数据存储,节约开发成本。
优化多表 Join 分析查询场景的性能,使用 Colocation Join ,通过预先的数据分布,减少节点间网络传输带来的延迟开销,进一步提升查询性能。
使用 StarRocks 统一数据分析层,并在更多的业务中使用 StarRocks 。
7. 信也科技 x StarRocks:打造统一销售数据平台8. 汽车之家 x StarRocks:极速实时数据分析实践
如希望了解更多详情请关注我们!
联系电话:010-53322390
商务合作:bd@starrocks.com