排序键和前缀索引
在建表时,您可以指定一个或多个列构成排序键 (Sort Key)。表中的行会根据排序键进行排序以后再落入磁盘存储。查询数据时,您可以使用排序列指定过滤条件,StarRocks 不需要扫描全表即可快速找到需要处理的数据,降低搜索的复杂度,从而加速查询。
同时,为减少内存开销,StarRocks 在排序键的基础上又引入了前缀索引 (Prefix Index)。前缀索引是一种稀疏索引。表中每 1024 行数据构成一个逻辑数据块 (Data Block)。每个逻辑数据块在前缀索引表中存储一个索引项,索引项的长度不超过 36 字节,其内容为数据块中第一行数据的排序列组成的前缀,在查找前缀索引表时可以帮助确定该行数据所在逻辑数据块的起始行号。前缀索引的大小会比数据量少 1024 倍,因此会全量缓存在内存中,在实际查找的过程中可以有效加速查询。
排序原理
在明细模型中,排序列就是通过 DUPLICATE KEY
关键字指定的列。
在聚合模型中,排序列就是通过 AGGREGATE KEY
关键字指定的列。
在更新模型中,排序列就是通过 UNIQUE KEY
关键字指定的列。
自 3.0 版本起,主键模型解耦了主键列和排序列,排序列通过 ORDER BY
关键字指定,主键列通过 PRIMARY KEY
关键字指定。
在明细模型、聚合模型、更新模型中定义排序列时,需要注意以下几点:
-
排序列必须从定义的第一列开始、并且是连续的。
-
在定义各列时,计划作为排序列的列必须定义在其他普通列之前。
-
排序列的顺序必须与表定义的列顺序一致。
例如,建表语句中声明要创建 site_id
、city_code
、user_id
和 pv
四列。这种情况下,正确的排序列组合和错误的排序列组合举例如下:
-
正确的排序列
site_id
和city_code
site_id
、city_code
和user_id
-
错误的排序列
city_code
和site_id
city_code
和user_id
site_id
、city_code
和pv
下面通过示例来说明如何创建使用各个数据模型的表,以下建表语句适用于至少部署三个 BE 节点的集群环境下。
明细模型
创建一个名为 site_access_duplicate
的明细模型表,包含 site_id
、city_code
、user_id
和 pv
四列,其中 site_id
和 city_code
为排序列。
建表语句如下:
CREATE TABLE site_access_duplicate
(
site_id INT DEFAULT '10',
city_code SMALLINT,
user_id INT,
pv BIGINT DEFAULT '0'
)
DUPLICATE KEY(site_id, city_code)
DISTRIBUTED BY HASH(site_id);
注意
自 2.5.7 版本起,StarRocks 支持在建表和新增分区时自动设置分桶数量 (BUCKETS),您无需手动设置分桶数量。更多信息,请参见 确定分桶数量。
聚合模型
创建一个名为 site_access_aggregate
的聚合模型表,包含 site_id
、city_code
、user_id
和 pv
四列,其中 site_id
和 city_code
为排序列。
建表语句如下:
CREATE TABLE site_access_aggregate
(
site_id INT DEFAULT '10',
city_code SMALLINT,
user_id BITMAP BITMAP_UNION,
pv BIGINT SUM DEFAULT '0'
)
AGGREGATE KEY(site_id, city_code)
DISTRIBUTED BY HASH(site_id);
注意
聚合模型表中,如果某列未指定
agg_type
,则该列为 Key 列;如果某列指定了agg_type
,则该列为 Value 列。参见 CREATE TABLE。上述示例指定排序列为site_id
和city_code
,因此必须给user_id
和pv
列分别指定agg_type
。
更新模型
创建一个名为 site_access_unique
的更新模型表,包含 site_id
、city_code
、user_id
和 pv
四列,其中 site_id
和 city_code
为排序列。
建表语句如下:
CREATE TABLE site_access_unique
(
site_id INT DEFAULT '10',
city_code SMALLINT,
user_id INT,
pv BIGINT DEFAULT '0'
)
UNIQUE KEY(site_id, city_code)
DISTRIBUTED BY HASH(site_id);