主键表
- 优势:支撑实时数据更新的同时,也能保证高效的复杂即席查询性能
- 主键表中的主键具有唯一非空约束,用于唯一标识数据行,如果新数据的主键值与表中原数据的主键值相同,则存在唯一约束冲突,此时新数据会替代原数据
应用场景
- 实时对接事务型数据至StarRocks。事务型数据库中,除了插入数据外,一般还会涉及较多更新和删除数据的操作,因此事务型数据库的数据同步至StarRocks时,建议使用主键表
- 利用部分列更新轻松实现多流JOIN。在用户画像等分析场景中,一般会采用大宽表方式来提升多维分析的性能,同时简化数据分析师的使用模型。而这种场景中的上游数据,往往可能来自于多个不同业务或系统,主键表的部分列更新功能就很好地满足这种需求,不同业务直接各自按需更新与业务相关的列即可
工作原理
- 主键表采用了Delete+Insert策略,借助主键索引配合DelVector的方式实现,保证在查询时只需要读取具有相同主键值的数据中的最新数据,StarRocks会加载导入数据对应Tablet的主键索引至内存中
数据写入
- 数据写入是通过StarRocks内部的Loadjob实现,包含一批数据变更操作(包括Insert、Update、Delete),并且会更新主键索引中变更的数据行现在所在的数据文件和行号
Delete操作:通过主键索引找到数据行原来所在的数据文件以及行号,在DelVector(用于存储和管理数据导入时生成数据行对应的删除标记)中把该条数据标记为删除
Update操作:除了在DelVector中将原先数据行标记为删除,还会把最新数据写入新的数据文件,相当于把Update改写为Delete+Insert
数据读取
- 由于写入数据时各个数据文件中历史重复数据已经标记为删除,同一个主键值下仅需要读取最新的一条数据,无需在线Merge多个版本的数据文件来去重以找到最新的数据
使用说明
- 在CREATE TABLE语句通过PRIMARY KEY定义主键,即可创建一个主键表
建表示例
CREATE TABLE orders1 (
order_id bigint NOT NULL,
dt date NOT NULL,
user_id INT NOT NULL,
good_id INT NOT NULL,
cnt int NOT NULL,
revenue int NOT NULL
)
PRIMARY KEY (order_id)
DISTRIBUTED BY HASH (order_id)
;
- 假设经常根据订单日期和商户组合维度查询商品销售情况,可以通过ORDER BY(dt,merchant_id)指定排序键为dt和merchant_id
- 如果使用了数据分布策略,由于目前主键表要求主键必须包括分区列和分桶列,假设采用的数据分布策略是将dt作为分区列并且merchant_id作为哈希分桶列,则主键还需要包括dt和merchant_id
CREATE TABLE orders2 (
order_id bigint NOT NULL,
dt date NOT NULL,
merchant_id int NOT NULL,
user_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 (order_id,dt,merchant_id)
PARTITION BY date_trunc('day', dt)
DISTRIBUTED BY HASH (merchant_id)
ORDER BY (dt,merchant_id)
PROPERTIES (
"enable_persistent_index" = "true"
);
主键
- 主键用于唯一标识表中的每一行数据,组成主键的一个或多个列在PRIMARY KEY中定义,具有非空唯一性约束
1、在建表语句中,主键列必须定义在其他列之前
2、主键必须包含分区列和分桶列
3、主键列支持以下数据类型:数值(包括整型和布尔)、日期和字符串
4、默认设置下,单条主键值编码后的最大长度为128字节
5、建表后不支持修改主键
6、主键列的值不能更新,避免破坏数据一致性
主键索引
- 保存主键值和其标识的数据行所在位置的映射
- 通常只有在导入数据(包含一批数据变更)的时候会将导入数据相关Tablet的主键索引加载至内存
enable_persistent_index
:设置为true(默认),表示持久化主键索引,通常情况下,持久化主键索引后,查询和更新性能几乎接近全内存索引- StarRocks存算分离集群支持基于本地磁盘上的持久化索引,可以通过将主键表
persistent_index_type
设置为CLOUD_NATIVE启用该功能
排序键
- 排序键由ORDER BY定义的排序列组成,可以为任意列的排列组合,只要列的数据类型满足排序键的要求
- 排序键还用于构建前缀索引,能够加速查询
- 建表后支持通过
ALTER TABLE ... ORDER BY ...
修改排序键,不支持删除排序键,不支持修改排序列的数据类型
明细表
- 明细表是默认创建的表类型,如果在建表时未指定任何key,默认创建的是明细表
- 建表时支持定义排序键,如果查询的过滤条件包含排序键,则StarRocks能够快速地过滤数据,提高查询效率
- 支持追加新数据,不支持修改历史数据
适用场景
- 分析原始数据,例如原始日志、原始操作记录等
- 查询方式灵活,不需要局限于预聚合的分析方式
- 导入日志数据或者时序数据,主要特点是旧数据不会更新,只会追加新的数据
创建表
- 分析某时间范围的某一类事件的数据,则可以将事件时间(event_time)和事件类型(event_type)作为排序键
CREATE TABLE 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 "")
ORDER BY (event_time, event_type);
- 如果同时使用ORDER BY和DUPLICATE KEY,则DUPLICATE KEY无效,如果未使用ORDER BY和DUPLICATE KEY,则默认选择表的前三列作为排序键
- 如果导入两行完全相同的数据,则明细表会将这两行数据视为两行,而不是一行