StarRocks 中的数据模型和索引使用

一、StarRocks 数据模型

StarRocks 支持四种数据模型,分别是明细模型 (Duplicate Key Model)、聚合模型 (Aggregate Key Model)、更新模型 (Unique Key Model) 和主键模型 (Primary Key Model)。

1.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 of ",
   channel INT COMMENT ""
) DUPLICATE KEY(event_time, event_type)
DISTRIBUTED BY HASH(user_id)  BUCKETS 8 ;

1.2 聚合模型

在数据分析中,很多场景需要基于明细数据进行统计和汇总,这个时候就可以使用聚合模型。比如:统计app访问流量、用户访问时长、用户访问次数、展示总量、消费统计等等场景。

例如:

CREATE TABLE IF NOT EXISTS 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",
    mt BIGINT MAX
)
DISTRIBUTED BY HASH(site_id) BUCKETS 8;

1.3 更新模型

有些分析场景之下,数据需要进行更新比如拉链表,StarRocks则采用更新模型来满足这种需求,比如电商场景中,订单的状态经常会发生变化,每天的订单更新量可突破上亿。这种业务场景下,如果只靠明细模型下通过delete+insert的方式,是无法满足频繁更新需求的,因此,可以使用更新模型来满足分析需求。但是如果用户需要更加实时/频繁的更新操作,建议使用主键模型。

例如:

CREATE TABLE IF NOT EXISTS update_detail (
    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

1.4 主键模型

相比较更新模型,主键模型可以更好地支持实时/频繁更新的功能。虽然更新模型也可以实现实时对数据的更新,但是更新模型采用Merge on Read读时合并策略会大大限制查询功能,在主键模型更好地解决了行级的更新操作。配合Flink-connector-starrocks可以完成Mysql CDC实时同步的方案。

需要注意的是:由于存储引擎会为主键建立索引,导入数据时会把索引加载到内存中,所以主键模型对内存的要求更高,所以不适合主键模型的场景还是比较多的。
目前比较适合使用主键模型的场景有这两种:

  1. 数据冷热特征,比如最近几天的数据才需要修改,老的冷数据很少需要修改,比如订单数据,老的订单完成后就不在更新,并且分区是按天进行分区的,那么在导入数据时历史分区的数据的主键就不会被加载,也就不会占用内存了,内存中仅会加载近几天的索引。

  2. 大宽表(数百列数千列),主键只占整个数据的很小一部分,内存开销比较低。比如用户状态/画像表,虽然列非常多,但总的用户数量不大(千万-亿级别),主键索引内存占用相对可控。

原理:由于更新模型采用Merge策略,使得谓词无法下推和索引无法使用,严重影响
查询性能。所以主键模型通过主键约束,保证同一个主键仅存一条数据的记录,这样就规避了Merge操作。

StarRocks收到对某记录的更新操作时,会通过主键索引找到该条数据的位置,并对其标记为删除,再插入一条数据,相当于把update改写为delete+insert

例如:

CREATE TABLE users (
    user_id BIGINT NOT NULL,
    NAME STRING NOT NULL,
    email STRING NULL,
    address STRING NULL,
    age TINYINT NULL,
    sex TINYINT NULL
) PRIMARY KEY (user_id)
DISTRIBUTED BY HASH(user_id) BUCKETS 4

二、排序键和前缀索引

在建表时,可以指定一个或多个列构成排序键 (Sort Key)。表中的行会根据排序键进行排序以后再落入磁盘存储。查询数据时,您可以使用排序列指定过滤条件,StarRocks 不需要扫描全表即可快速找到需要处理的数据,降低搜索的复杂度,从而加速查询。

同时,为减少内存开销,StarRocks 在排序键的基础上又引入了前缀索引 (Prefix Index)。前缀索引是一种稀疏索引。表中每 1024 行数据构成一个逻辑数据块 (Data Block)。每个逻辑数据块在前缀索引表中存储一个索引项,索引项的长度不超过 36 字节,其内容为数据块中第一行数据的排序列组成的前缀,在查找前缀索引表时可以帮助确定该行数据所在逻辑数据块的起始行号。前缀索引的大小会比数据量少 1024 倍,因此会全量缓存在内存中,在实际查找的过程中可以有效加速查询。

在明细模型中,排序列就是通过 DUPLICATE KEY 关键字指定的列。

在聚合模型中,排序列就是通过 AGGREGATE KEY 关键字指定的列。

在更新模型中,排序列就是通过 UNIQUE KEY 关键字指定的列。

3.0 版本起,主键模型解耦了主键列和排序列,排序列通过 ORDER BY 关键字指定,主键列通过 PRIMARY KEY 关键字指定。

在明细模型、聚合模型、更新模型中定义排序列时,需要注意以下几点:

  • 排序列必须从定义的第一列开始、并且是连续的。

  • 在定义各列时,计划作为排序列的列必须定义在其他普通列之前。

  • 排序列的顺序必须与表定义的列顺序一致。

例如主键模型下添加排序键:

CREATE TABLE site_access_primary
(
    site_id INT DEFAULT '10',
    city_code SMALLINT,
    user_id INT,
    pv BIGINT DEFAULT '0'
)
PRIMARY KEY(site_id)
DISTRIBUTED BY HASH(site_id) BUCKETS 10
ORDER BY(site_id,city_code);

三、索引

3.1 Bitmap 索引

在这里插入图片描述

Bitmap 索引是一种使用 bitmap 的特殊数据库索引。bitmap 即为一个 bit 数组,一个 bit 的取值有两种:01。每一个 bit 对应数据表中的一行,并根据该行的取值情况来决定 bit 的取值是 0 还是 1

Bitmap 索引能够提高指定列的查询效率。如果一个查询条件命中前缀索引列,StarRocks 即可使用前缀索引提高查询效率,快速返回查询结果。但是前缀索引的长度有限,如果想要提高一个非前缀索引列的查询效率,即可以为这一列创建 Bitmap 索引。

优点

  • 对于基数较低,值大量重复,例如 ENUM 类型的列,使用 Bitmap 索引能够减少查询的响应时间。

  • Bitmap 索引所占的存储空间通常只有索引数据的一小部分,与其他索引技术相比,更节省存储空间。

  • 支持为多个列创建 Bitmap 索引,提高多列查询的效率,具体参见多列查询。

使用

  • Bitmap 索引适用于可使用等值条件 (=) 查询或 [NOT] IN 范围查询的列。
  • 主键模型和明细模型中所有列都可以创建 Bitmap 索引;聚合模型和更新模型中,只有维度列(即 Key 列)支持创建 bitmap 索引。
  • 不支持为 FLOATDOUBLEBOOLEANDECIMAL 类型的列创建 Bitmap 索引。
  • 如要了解一个查询是否命中了 Bitmap 索引,可查看该查询的 Profile 中的 BitmapIndexFilterRows 字段。

创建索引:

CREATE TABLE test
(
    k1 TINYINT,
    k2 DECIMAL(10, 2) DEFAULT "10.5",
    v1 CHAR(10) REPLACE,
    v2 INT SUM,
    INDEX index_name (v1) USING BITMAP COMMENT 'index_name '
)
ENGINE = olap
AGGREGATE KEY(k1, k2)
DISTRIBUTED BY HASH(k1) BUCKETS 10
PROPERTIES ("storage_type" = "column");

或者:

CREATE INDEX index_name ON test(v1) USING BITMAP COMMENT 'index_name ';

查看创建进度:

SHOW ALTER TABLE v1 FROM test;

查看索引:

SHOW INDEX FROM test;

删除索引:

DROP INDEX index_name ON test;

3.2 Bloom filter 索引

在这里插入图片描述

Bloom filter 索引可以快速判断表的数据文件中是否可能包含要查询的数据,如果不包含就跳过,从而减少扫描的数据量。Bloom filter 索引空间效率高,适用于基数较高的列,如 ID 列。如果一个查询条件命中前缀索引列,StarRocks 会使用前缀索引快速返回查询结果。但是前缀索引的长度有限,如果想要快速查询一个非前缀索引列且该列基数较高,即可为这个列创建 Bloom filter 索引。

说明

  • 主键模型和明细模型中所有列都可以创建 Bloom filter 索引;聚合模型和更新模型中,只有维度列(即 Key 列)支持创建 Bloom filter 索引。

  • 不支持为 TINYINTFLOATDOUBLEDECIMAL 类型的列创建 Bloom filter 索引。

  • Bloom filter 索引只能提高包含 in= 过滤条件的查询效率。

  • 如要了解一个查询是否命中了 Bloom filter 索引,可查看该查询的 Profile 中的 BloomFilterFilterRows 字段。

创建索引:

CREATE TABLE table1
(
    k1 BIGINT,
    k2 LARGEINT,
    v1 VARCHAR(2048) REPLACE,
    v2 SMALLINT DEFAULT "10"
)
ENGINE = olap
PRIMARY KEY(k1, k2)
DISTRIBUTED BY HASH (k1, k2) BUCKETS 10
PROPERTIES("bloom_filter_columns" = "k1,k2");

或者:

ALTER TABLE table1 SET ("bloom_filter_columns" = "k1,k2,v1");

查看索引:

SHOW CREATE TABLE table1;

删除索引:

ALTER TABLE table1 SET ("bloom_filter_columns" = "");

猜你喜欢

转载自blog.csdn.net/qq_43692950/article/details/130913021