StarRocks 新一代极速全场景MPP数据库

发布时间 2023-11-07 17:12:15作者: 大树2

StarRocks 介绍

1.StarRocks介绍
StarRocks是新一代极速全场景MPP数据库。
StarRocks充分吸收关系型OLAP数据库和分布式存储系统在大数据时代的优秀研究成果,在业界实践的基础上,进一步改进优化、升级架构,并增添了众多全新功能,形成了全新的企业级产品。
StarRocks致力于构建极速统一分析体验,满足企业用户的多种数据分析场景,支持多种数据模型(明细模型、聚合模型、更新模型),多种导入方式(批量和实时),支持导入多达10000列的数据,可整合和接入多种现有系统(Spark、Flink、Hive、 ElasticSearch)。
StarRocks兼容MySQL协议,可使用MySQL客户端和常用BI工具对接StarRocks来进行数据分析。
StarRocks采用分布式架构,对数据表进行水平划分并以多副本存储。集群规模可以灵活伸缩,能够支持10PB级别的数据分析; 支持MPP框架,并行加速计算; 支持多副本,具有弹性容错能力。
StarRocks采用关系模型,使用严格的数据类型和列式存储引擎,通过编码和压缩技术,降低读写放大;使用向量化执行方式,充分挖掘多核CPU的并行计算能力,从而显著提升查询性能。
从用途上来说,StarRocks可用于海量数据的高速查询场景,并兼容MySQL协议。

2.StarRocks 基本概念及系统架构

3.手动部署
这一节可以忽略,一般会有专门的集群运维人员负责,作为用户基本无需关注。

4.表创建
StarRocks的语法在ANSI-SQL的基础上有所改动,很多特性需要用特定的关键字声明。

排序键
分区分桶
数据模型
索引
ENGINE类型
数据导入和查询

StarRocks的数据导入,支持Spark、Kafka、MySQL等多种类型;查询上,它兼容MySQL协议,任何原本用于连接MySQL的BI工具或客户端都可以用于连接StarRocks。

5.表设计
理解StarRocks表设计
StarRocks性能优秀的原因主要有:

列式存储;
索引;
多种加速处理方式;
建表语句demo

create table testa (
event string NULL COMMENT ""
, id string NULL COMMENT ""
, dteventtime datetime NULL COMMENT ""
, roleid string NULL COMMENT ""
, osid string NULL COMMENT ""
, userid string NULL COMMENT ""
)
ENGINE = OLAP
DUPLICATE KEY(event, id, dteventtime)
COMMENT "OLAP"
PARTITIon BY RANGE(dteventtime) (
PARTITIon p20220919 VALUES [('2022-09-19 00:00:00'), ('2022-09-20 00:00:00')),
PARTITIon p20220920 VALUES [('2022-09-20 00:00:00'), ('2022-09-21 00:00:00')),
PARTITIon p20220921 VALUES [('2022-09-21 00:00:00'), ('2022-09-22 00:00:00'))
)
DISTRIBUTED BY HASH(vopenid)
BUCKETS 64
PROPERTIES (
"replication_num" = "3",
"dynamic_partition.enable" = "true",
"dynamic_partition.time_unit" = "DAY",
"dynamic_partition.time_zone" = "Asia/Shanghai",
"dynamic_partition.start" = "-2147483648",
"dynamic_partition.end" = "30",
"dynamic_partition.prefix" = "p",
"dynamic_partition.buckets" = "4",
"colddown_max_bytes_per_file" = "134217728",
"in_memory" = "false",
"storage_format" = "DEFAULT"
);

CREATE TABLE testb (
id string
, dteventtime string
, userid string
, osid string
, product_id string
) ENGINE=OLAP
DUPLICATE KEY(id, dteventtime, userid)
COMMENT "OLAP"
PARTITION BY RANGE(dteventtime)
DISTRIBUTED BY HASH(userid)
BUCKETS 256 PROPERTIES (
"replication_num" = "3",
"colocate_with" = "testb",
"dynamic_partition.enable" = "true",
"dynamic_partition.time_unit" = "DAY",
"dynamic_partition.time_zone" = "Asia/Shanghai",
"dynamic_partition.start" = "-30",
"dynamic_partition.end" = "30",
"dynamic_partition.prefix" = "p",
"dynamic_partition.buckets" = "256",
"colddown_max_bytes_per_file" = "134217728",
"in_memory" = "false",
"storage_format" = "DEFAULT"
)
;

6.数据模型介绍
在StarRocks中建表时,需要用户指定 数据模型。数据在被导入StarRocks时,会根据数据模型、对数据进行排序和存储等预处理,以便提升分析和查询的性能。

四种数据模型分为以下几类:

明细模型 (Duplicate Key Model)
聚合模型 (Aggregate Key Model)
更新模型 (Unique Key Model)
主键模型 (Primary Key Model)
在建表时需要指定 排序键,对于常用的明细模型来说,它由关键字 duplicate key 来指定。排序键需要选定查询时常用的维度列,并且可重复,不必满足唯一性约束。

6.1明细模型(重点)
明细模型适用于日志数据分析等场景,仅支持数据的增删、不支持修改。

CREATE TABLE IF NOT EXISTS detail (
event_time DATETIME NOT NULL COMMENT "datetime of event",
event_type INT NOT NULL COMMENT "type of event",
user_id INT COMMENT "id of user",
device_code INT COMMENT "device code",
channel INT COMMENT ""
)
DUPLICATE KEY(event_time, event_type) -- 指定排序键
DISTRIBUTED BY HASH(user_id) BUCKETS 8 -- 指定分桶键
;

CREATE TABLE IF NOT EXISTS tmp (
userid VARCHAR(200) NOT NULL,
dteventtime VARCHAR(100) NOT NULL,
game_id VARCHAR(100) NOT NULL
)
COMMENT '明细模型表 - 游戏矩阵注册事件'
DISTRIBUTED BY HASH(identity)
PROPERTIES (
'replication_num' = '1',
'in_memory' = 'false'
);

6.2聚合模型
聚合模型适用于统计和汇总数据,例如统计网站的访问总次数、统计电商全年的销售额。

我的疑问:明细模型也可以用于统计,那么聚合模型相比明细模型,优势在哪里?全部聚合统计场景,我也全部都用聚合模型可行吗?
CREATE TABLE IF NOT EXISTS example_db.aggregate_tbl (
site_id LARGEINT NOT NULL COMMENT "id of site",
date DATE NOT NULL COMMENT "time of event",
city_code VARCHAR(20) COMMENT "city_code of user",
pv BIGINT SUM DEFAULT "0" COMMENT "total page views"
)
DISTRIBUTED BY HASH(site_id) BUCKETS 8;

6.3更新模型
更新模型适用于频繁更新的场景,例如电商系统中每天上亿张订单的状态可能发生改变,对这类场景进行分析就可以使用更新模型。

CREATE TABLE IF NOT EXISTS orders (
create_time DATE NOT NULL COMMENT "create time of an order",
order_id BIGINT NOT NULL COMMENT "id of an order",
order_state INT COMMENT "state of an order",
total_price BIGINT COMMENT "price of an order"
)
UNIQUE KEY(create_time, order_id)
DISTRIBUTED BY HASH(order_id) BUCKETS 8;

6.4主键模型
主键模型是性能增强的更新模型。

那么问题来了,是否可以完全不用更新模型了,全部切换主键模型??
create table orders (
dt date NOT NULL,
order_id bigint NOT NULL,
user_id int NOT NULL,
merchant_id int NOT NULL,
good_id int NOT NULL,
good_name string NOT NULL,
price int NOT NULL,
cnt int NOT NULL,
revenue int NOT NULL,
state tinyint NOT NULL
) PRIMARY KEY (dt, order_id)
PARTITION BY RANGE(dt) (
PARTITION p20210820 VALUES [('2021-08-20'), ('2021-08-21')),
PARTITION p20210821 VALUES [('2021-08-21'), ('2021-08-22')),
...
PARTITION p20210929 VALUES [('2021-09-29'), ('2021-09-30')),
PARTITION p20210930 VALUES [('2021-09-30'), ('2021-10-01'))
) DISTRIBUTED BY HASH(order_id) BUCKETS 4
PROPERTIES("replication_num" = "3");

7.数据分布(重点)
数据分布是指将数据划分为子集,并按一定规则均衡地分布在EF的不同节点上。合理的数据分布,能够有效减少数据扫描量,最大限度地利用集群的并发性能,从而提升查询性能。

常见的数据分布有如下几种:

Round-Robin:以轮询的方式把数据逐个放置在相邻节点上。例如,将编号为001-006的六个用户id放置在三台服务器(编号为A、B、C)上,以这种数据分布方式进行排布,结果就是,服务器A存储001、004,服务器B存储002、005,服务器C存储003、006;
Range:按区间进行数据分布。例如,将编号为001-006的六个用户id放置在三台服务器(编号为A、B、C)上,如果我们约定001-002是一个区间、003-004是一个区间、005-006是一个区间,那么这三个区间会分别放置在三台服务器上,这就是Range;
List:直接基于离散的各个取值做数据分布。例如,性别(男、女)是一种离散枚举值,我们约定将“男、女、未知”的数据分别存储在服务器A、B、C,这就是List;
Hash:通过哈希函数把数据映射到不同节点上;
哈希函数是一种将任意长度的输入数据映射为固定长度输出数据的函数,一般用于数据加密、数据校验、索引、分布式存储等场景。常见的哈希函数有MD5、SHA-1、SHA-256。

8.StarRocks 支持如下两种数据分布方式:

Hash 数据分布方式:一张表为一个分区,分区按照分桶键和分桶数量进一步进行数据划分。建表语句如下。
CREATE TABLE site_access(
site_id INT DEFAULT '10',
city_code SMALLINT,
user_name VARCHAR(32) DEFAULT '',
pv BIGINT SUM DEFAULT '0'
)
AGGREGATE KEY(site_id, city_code, user_name)
DISTRIBUTED BY HASH(site_id) BUCKETS 10;
Range+Hash 数据分布方式:一张表拆分成多个分区,每个分区按照分桶键和分桶数量进一步进行数据划分。建表语句如下。
CREATE TABLE site_access(
event_day DATE,
site_id INT DEFAULT '10',
city_code VARCHAR(100),
user_name VARCHAR(32) DEFAULT '',
pv BIGINT SUM DEFAULT '0'
)
AGGREGATE KEY(event_day, site_id, city_code, user_name)
PARTITION BY RANGE(event_day)
(
PARTITION p1 VALUES LESS THAN ("2020-01-31"),
PARTITION p2 VALUES LESS THAN ("2020-02-29"),
PARTITION p3 VALUES LESS THAN ("2020-03-31")
)
DISTRIBUTED BY HASH(site_id) BUCKETS 10;
StarRocks中的数据分布优化,是通过 分区和分桶来完成的。

分区。分区?于将数据划分成不同的区间,分区的主要作?是将?张表按照分区键拆分成不同的管理单元,针对每?个管理单元选择相应的存储策略,?如副本数、冷热策略和存储介质等等。对于访问频率高的分区,可以使用SSD存储;对于访问频率低的分区,可以使用STAT存储。选择合理的分区键可以有效的裁剪扫描的数据量,一般选择日期或者区域作为分区键;
分桶。分区的下?级是分桶,StarRocks 采? Hash 算法作为分桶算法。在同?分区内,分桶键哈希值相同的数据形成 Tablet,Tablet 以多副本冗余的形式存储,是数据均衡和恢复的最?单位。选择高基数的列(例如用户id)来作为分桶键,可以保证数据在各个分桶中尽可能均衡;如何确定合适的分桶数量?

排序键和前缀索引
排序键的作用是,在数据写入StarRocks、落入磁盘存储之前,表中的行会先根据排序键进行排序。这样一来,查询数据的时候就无需扫描全表数据了,从而加快了查询速度。

这里我们举例来说明排序键再数据查询时的作用。假设一张表仅有一个字段userid,在建表时我们指定userid为排序键,它的取值范围是1到10000。我们现在要查询userid=5893的数据,StarRocks的执行过程是怎样的呢?以下以二分法作为查询算法来说明:

第一步,用二分查找1-10000的userid,返回5000,它小于目标值5893,因此下一步需要向右查找;
第二步,用二分查找5000-10000的userid,返回7500,它大于目标值5893,因此下一步需要向左查找;
第三步,用二分查找5000-7500的userid,返回6250,它大于目标值5893,因此下一步需要向左查找;
第四步,用二分查找5000-6250的userid,返回5625,它小于目标值5893,因此下一步需要向右查找;
第五步,用二分查找5625-6250的userid,返回5927,它大于目标值5893,因此下一步需要向左查找;
....
以此类推,直到找到了userid为5893的枚举值;

9.导入数据
数据导入到StarRocks,分为两类:

同步导入。导入速度慢,需要等待数据导入任务执行完毕之后,才能进行ETL、数据分析等操作。一般适用于小批量的数据导入;
异步导入。导入速度快,可以边导入、边使用数据,但是导入稳定性需要监控。一般适用于大批量的数据导入;
至于具体的导入方法,在用的时候再查询文档就行了。阅读文档的时候不需要逐个浏览。

10.导出数据
数据可以用StarRocks导出到HDFS、Spark、Flink等系统,用于开发业务需求。

同上,详细的导出方式也不用细看,用的时候再看。

11.常用语法
-- 查看建表语句show create table t_test
-- 查询分区show partitions from t_test;
-- 手动新增分区alter table t_test set ("dynamic_partition.enable" = "false") -- 关闭动态分区alter table t_test add partitions start ('2022-01-01') end ('2022-01-02') every (interval 1 day) -- 新增区间,左闭右开alter table t_test set ("dynamic_partition.enable" = "true") -- 开启动态分区-- 删除分区alter table t_test drop partition p20220101;

转载:https://zhuanlan.zhihu.com/p/633280344?utm_id=0