基于starRocks官方文档,对其内容进行一定解析,方便大家理解和使用。
若无特殊标注,startRocks版本是3.2。
下面的章节和官方文档保持一致。
产品简介 | StarRocks
StarRocks 是一款高性能分析型数据仓库,使用向量化、MPP 架构、CBO、智能物化视图、可实时更新的列式存储引擎等技术实现多维、实时、高并发的数据分析。StarRocks 既支持从各类实时和离线的数据源高效导入数据,也支持直接分析数据湖上各种格式的数据。StarRocks 兼容 MySQL 协议,可使用 MySQL 客户端和常用 BI 工具对接。同时 StarRocks 具备水平扩展,高可用、高可靠、易运维等特性。广泛应用于实时数仓、OLAP 报表、数据湖分析等场景。
内容 | 说明 |
---|---|
高性能分析型数据仓库 | 相比于oltp,更适合olap |
向量化 | 基于CPU层级的优化(clickhouse有相关优化) |
MPP 架构 | 相比于hadoop架构更适合olap |
CBO | 优化多表join的执行时,starRocks内部的执行先后顺序 |
智能物化视图 | 用于实现单表的实时数据转换,类似clickhouse的物化视图 |
可实时更新的列式存储引擎 | 可支持实时update |
兼容 MySQL | 可使用mysql相关语法和client工具 |
如图所示,一般数据库只有database和table两层,但因为starRocks是湖仓一体化的设计,可以读取外部数据源,所以在外面增加一层进行区分。相当于原来是两层目录,现在是三层目录。
除了常规的视图外,还提供了物化视图。物化视图还分为同步物化视图和异步物化视图,前者相对简单,作用于单表,后者的功能相对复杂,作用于多表。
支持权限控制,分为基于用户标识的访问控制和基于角色的访问控制。
简单说明表相关信息,入门说明。
有几种表类型,数据怎么分布的,数据有哪些类型,以及其他特性。
StarRocks 支持四种数据模型,分别是明细模型 (Duplicate Key Model)、聚合模型 (Aggregate Key Model)、更新模型 (Unique Key Model) 和主键模型 (Primary Key Model)。主键模型逐渐替代更新模式,所以只需要关注三种模型。
单纯的事实表,只是把数据写入,不涉及更新合并。适合作为ods层建表,用于存储每天接入的数据。
建表有两个地方需要注意:
DUPLICATE KEY:排序键,不会触发去重,但会影响查询效率(因为数据是按照排序键排列的,影响检索效率)。
DISTRIBUTED BY:默认要配置分桶,降低数据倾斜的风险
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)
PROPERTIES (
"replication_num" = "3"
);
相当于实现sum groupby key。但存在的问题是,无法回滚到历史。建议用于ads层,聚合逻辑场景,且如果遇到脏数据,重新计算的成本相对低。
建表有三个地方需要注意:
AGGREGATE KEY:排序键,但会影响查询效率(因为数据是按照排序键排列的,影响检索效率)。【如果不配置这项,则默认是非指标计算的其他列。但建议是显示配置,因为显示配置,如果有列既不是排序键,又不是指标列,则会建表报错】
DISTRIBUTED BY:默认要配置分桶,降低数据倾斜的风险
聚合函数配置:支持SUM、MAX、MIN等可累加的函数
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"
)
AGGREGATE KEY(site_id, date, city_code)
DISTRIBUTED BY HASH(site_id)
PROPERTIES (
"replication_num" = "3"
);
可以不关注,反正后续被主键模型替代。
更新模型整体上采用了 Merge-On-Read 的策略。虽然写入时处理简单高效,但是查询时需要在线聚合多版本。并且由于 Merge 算子的存在,谓词和索引无法下推,严重影响了查询性能。
主键模型采用了 Delete+Insert 的策略,保证同一个主键下仅存在一条记录,这样就完全避免了 Merge 操作。【存储换时间,通过直接对数据进行标记,如果发生替换,则直接对旧数据标记为-1,这样查询的时候,直接过滤即可】
建表有两个地方需要注意:
PRIMARY KEY:主键,分区列和分桶列必须在,否则会影响查询效率(因为数据是按照主键排列的,影响检索效率)。
DISTRIBUTED BY:默认要配置分桶,降低数据倾斜的风险
ORDER BY:数据合并,可以根据这里的列(解决部分数据延迟,而旧数据更新的场景。例如:1号的订单,2号、3号分别发生状态变更,3号的数据先来,2号的数据后来,如果不配置其他列,模式是入库时间更新,会导致3号数据被删除,保留2号的状态。所以需要配置状态变更时间,而不是默认入库时间)
enable_persistent_index:是否支持索引持久化,就是索引对内存有压力,所以默认开启,可以持久化到磁盘上,降低内存溢出风险。
create table users (
user_id bigint NOT NULL,
name string NOT NULL,
email string NULL,
address string NULL,
age tinyint NULL,
sex tinyint NULL,
last_active datetime,
property0 tinyint NOT NULL,
property1 tinyint NOT NULL,
property2 tinyint NOT NULL,
property3 tinyint NOT NULL
) PRIMARY KEY (user_id)
DISTRIBUTED BY HASH(user_id)
ORDER BY(`address`,`last_active`)
PROPERTIES (
"replication_num" = "3",
"enable_persistent_index" = "true"
);
数据分布的核心是,通过分区、分桶来限制tablet大小【tablet,就是最小的存储单元,官方建议是在1-10GB】。太大的话,导致查询以及合并效率降低,太小的话,会增加内存压力和检索时长。
支持时间连续和枚举值,两种场景。
就是可以选择一个时间戳或则日期字段,配置一下分区粒度(现在支持hour、day、month、year,暂不支持week),就可以形成分区。
如果是之前的话,需要自己转换为对应样式才可以。
例如:“2024-01-05 11:11:33”,按照year分区,需要转换为“2024”,按照month分区,需要转化为“2024-01”,按照day分区,需要转换为“2024-01-05”。现在只需要配置hour、day、month、year枚举值即可。
partition_live_number:保留的分区数量,用于控制磁盘占用。
CREATE TABLE site_access2 (
event_day DATETIME NOT NULL,
site_id INT DEFAULT '10',
city_code VARCHAR(100),
user_name VARCHAR(32) DEFAULT '',
pv BIGINT DEFAULT '0'
)
DUPLICATE KEY(event_day, site_id, city_code, user_name)
PARTITION BY date_trunc('month', event_day)
DISTRIBUTED BY HASH(event_day, site_id)
PROPERTIES(
"partition_live_number" = "3" -- 只保留最近 3 个分区
);
周粒度的分区无法直接配置,但可以利用分区表达式 time_slice(),设置分区列为 event_day,分区粒度为七天。将一周的数据存储在一个分区中,利用分区裁剪可以显著提高查询效率
CREATE TABLE site_access3 (
event_day DATETIME NOT NULL,
site_id INT DEFAULT '10',
city_code VARCHAR(100),
user_name VARCHAR(32) DEFAULT '',
pv BIGINT DEFAULT '0'
)
DUPLICATE KEY(event_day, site_id, city_code, user_name)
PARTITION BY time_slice(event_day, INTERVAL 7 day)
DISTRIBUTED BY HASH(event_day, site_id);
最后,还有说明分区导入数据的方式。
需要手动创建分区。
就是类似咱们按照店铺分区,但现在说有些店铺算一起的,查询的时候不想一个个查,就给这些店铺增加一个统一的分区。
CREATE TABLE t_recharge_detail2 (
id bigint,
user_id bigint,
recharge_money decimal(32,2),
city varchar(20) not null,
dt varchar(20) not null
)
DUPLICATE KEY(id)
PARTITION BY LIST (city) (
PARTITION pCalifornia VALUES IN ("Los Angeles","San Francisco","San Diego"), -- 这些城市同属一个州
PARTITION pTexas VALUES IN ("Houston","Dallas","Austin")
)
DISTRIBUTED BY HASH(`id`);
和表达式分区相比,动态分区,只能支持时间类型的字段。好处是可以控制存储文件的范围。
CREATE TABLE site_access(
event_day DATE,
site_id INT DEFAULT '10',
city_code VARCHAR(100),
user_name VARCHAR(32) DEFAULT '',
pv BIGINT DEFAULT '0'
)
DUPLICATE KEY(event_day, site_id, city_code, user_name)
PARTITION BY RANGE(event_day)(
PARTITION p20200321 VALUES LESS THAN ("2020-03-22"),
PARTITION p20200322 VALUES LESS THAN ("2020-03-23"),
PARTITION p20200323 VALUES LESS THAN ("2020-03-24"),
PARTITION p20200324 VALUES LESS THAN ("2020-03-25")
)
DISTRIBUTED BY HASH(event_day, site_id)
PROPERTIES(
"dynamic_partition.enable" = "true",
"dynamic_partition.time_unit" = "DAY",
"dynamic_partition.start" = "-3",
"dynamic_partition.end" = "3",
"dynamic_partition.prefix" = "p",
"dynamic_partition.history_partition_num" = "0"
);
用于调整数据分布策略包括分区范围、分桶数、以及部分属性,例如副本数、存储介质。
类似咱们创建一张新表和原来字段一致,但数据分布策略有调整,重新导入数据。
因为支持原子替换(ALTERTABLE table1 SWAP WITH table2;),大概率这种比直接换表效率高。
应用场景:
StarRocks 支持四种数据压缩算法:LZ4、Zstandard(或 zstd)、zlib 和 Snappy。StarRocks 默认使用 LZ4,建表后不能修改压缩格式。
通常来说,这些算法的压缩率排名如下:zlib > Zstandard > LZ4 > Snappy。
但压缩率越高,导入和查询性能越差,因为需要解析的成本越高。
所以在内存空间没有硬性要求的情况下,建议选择使用 LZ4 或 Zstandard 算法。
前缀索引,相当于是排序键的索引。
查询数据时,您可以使用排序列指定过滤条件,StarRocks 不需要扫描全表即可快速找到需要处理的数据,降低搜索的复杂度,从而加速查询。
举个例子:根据日期+店铺排序,如果查询2023年1月份伊利的数据,那么只要找到2023年1月1日到2023年1月31日的数据,根据二分法,针对日期列进行检索,不需要判断每一行是不是。