Flink-StarRocks详解:第四部分StarRocks分区管理,数据压缩(第54天) ...

打印 上一主题 下一主题

主题 539|帖子 539|积分 1617


前言

本文为Flink-StarRocks详解后续章节:告急详解StarRocks分区分桶管理,数据压缩,
由于篇幅过长,后续接着下面举行详解:
 StarRocks查询数据湖
 实现即席查询案例
2.3.3 管理分区

2.3.3.1 增加分区

对于 Range 分区和 List 分区,可以手动增加新的分区,用于存储新的数据,而表达式分区可以实现导入新数据时自动创建分区,无需手动新增分区。 新增分区的默认分桶数量和原分区相同。也可以根据新分区的数据规模调解分桶数量。
如下示例中,在 site_access5 表添加新的分区,用于存储新月份的数据:
  1. ALTER TABLE test.site_access5
  2. ADD PARTITION p4 VALUES LESS THAN ("2020-04-30")
  3. DISTRIBUTED BY HASH(site_id);
复制代码
2.3.3.2 删除分区

实行如下语句,删除 site_access5 表中分区 p1 及数据:
说明:分区中的数据不会立即删除,会在 Trash 中保存一段时间(默以为一天)。假如误删分区,可以通过 RECOVER 命令恢复分区及数据。
  1. ALTER TABLE test.site_access5
  2. DROP PARTITION p1;
复制代码
2.3.3.3 恢复分区

实行如下语句,恢复 site_access5 表中分区 p1 及数据:
  1. RECOVER PARTITION p1 FROM test.site_access5;
复制代码
2.3.3.4 检察分区

实行如下语句,检察 site_access5 表中分区情况:
  1. SHOW PARTITIONS FROM test.site_access5;
复制代码
2.3.4 设置分桶

2.3.4.1 随机分桶(自 v3.1)

对每个分区的数据,StarRocks 将数据随机地分布在全部分桶中,适用于数据量不大,对查询性能要求不高的场景。假如不设置分桶方式,则默认由 StarRocks 使用随机分桶,并且自动设置分桶数量。
不外值得留意的是,假如查询海量数据且查询时经常使用一些列会作为条件列,随机分桶提供的查询性能可能不够抱负。在该场景下建议使用哈希分桶,当查询时经常使用这些列作为条件列时,只需要扫描和计算查询命中的少量分桶,则可以显著提高查询性能。
使用限制
 仅支持明细模型表。
 不支持指定 Colocation Group。
 不支持 Spark Load。
如下建表示例中,没有使用 DISTRIBUTED BY xxx 语句,即表示默认由 StarRocks 使用随机分桶,并且由 StarRocks 自动设置分桶数量。
  1. CREATE TABLE test.site_access9(
  2.     event_day DATE,
  3.     site_id INT DEFAULT '10',
  4.     pv BIGINT DEFAULT '0' ,
  5.     city_code VARCHAR(100),
  6.     user_name VARCHAR(32) DEFAULT ''
  7. )
  8. DUPLICATE KEY(event_day,site_id,pv)
  9. PROPERTIES (
  10.     "replication_num" = "1"
  11. );
复制代码
固然,假如比力熟悉 StarRocks 的分桶机制,使用随机分桶建表时,也可以手动设置分桶数量。
  1. CREATE TABLE test.site_access10(
  2.     event_day DATE,
  3.     site_id INT DEFAULT '10',
  4.     pv BIGINT DEFAULT '0' ,
  5.     city_code VARCHAR(100),
  6.     user_name VARCHAR(32) DEFAULT ''
  7. )
  8. DUPLICATE KEY(event_day,site_id,pv)
  9. DISTRIBUTED BY RANDOM BUCKETS 8 -- 手动设置分桶数量为 8
  10. PROPERTIES (
  11.     "replication_num" = "1"
  12. );
复制代码
2.3.4.2 哈希分桶

对每个分区的数据,StarRocks 会根据分桶键和分桶数量举行哈希分桶。在哈希分桶中,使用特定的列值作为输入,通过哈希函数计算出一个哈希值,然后将数据根据该哈希值分配到相应的桶中。
2.3.4.2.1 优点

 提高查询性能。相同分桶键值的行会被分配到一个分桶中,在查询时能减少扫描数据量。
 均匀分布数据。通过选取较高基数(唯一值的数量较多)的列作为分桶键,能更均匀的分布数据到每一个分桶中。
2.3.4.2.2 如何选择分桶键

假设存在列同时满足高基数和经常作为查询条件,则建议选择其为分桶键,举行哈希分桶。 假如不存在这些同时满足两个条件的列,则需要根据查询举行判断。
 假如查询比力复杂,则建议选择高基数的列为分桶键,保证数据在各个分桶中只管平衡,提高集群资源利用率。
 假如查询比力简单,则建议选择经常作为查询条件的列为分桶键,提高查询效率。
并且,假如数据倾斜情况严峻,还可以使用多个列作为数据的分桶键,但是建议不高出 3 个列。
2.3.4.2.3 留意事项

 建表时,假如使用哈希分桶,则必须指定分桶键。
 组身分桶键的列仅支持整型、DECIMAL、DATE/DATETIME、CHAR/VARCHAR/STRING 数据范例。
 分桶键指定后不支持修改。
如下示例中,site_access 表采用 site_id 作为分桶键,其原因在于 site_id 为高基数列。此外,针对 site_access 表的查询哀求,根本上都以站点作为查询过滤条件,采用 site_id 作为分桶键,还可以在查询时裁剪掉大量无关分桶。
  1. CREATE TABLE test.site_access11(
  2.     event_day DATE,
  3.     site_id INT DEFAULT '10',
  4.     city_code VARCHAR(100),
  5.     user_name VARCHAR(32) DEFAULT '',
  6.     pv BIGINT SUM DEFAULT '0'
  7. )
  8. AGGREGATE KEY(event_day, site_id, city_code, user_name)
  9. PARTITION BY RANGE(event_day) (
  10.     PARTITION p1 VALUES LESS THAN ("2020-01-31"),
  11.     PARTITION p2 VALUES LESS THAN ("2020-02-29"),
  12.     PARTITION p3 VALUES LESS THAN ("2020-03-31")
  13. )
  14. DISTRIBUTED BY HASH(site_id)
  15. PROPERTIES (
  16.     "replication_num" = "1"
  17. );
复制代码
如下查询中,假设每个分区有 10 个分桶,则其中 9 个分桶被镌汰,因而体系只需要扫描 site_access 表中 1/10 的数据:
  1. select sum(pv)
  2. from test.site_access11
  3. where site_id = 54321;
复制代码
但是假如 site_id 分布非常不均匀,大量的访问数据是关于少数网站的(幂律分布,二八规则),那么采用上述分桶方式会造成数据分布出现严峻的倾斜,进而导致体系局部的性能瓶颈。此时,需要适当调解分桶的字段,以将数据打散,避免性能问题。例如,可以采用 site_id、city_code 组互助为分桶键,将数据分别得更加均匀。干系建表语句如下:
  1. CREATE TABLE test.site_access12
  2. (
  3.     site_id INT DEFAULT '10',
  4.     city_code SMALLINT,
  5.     user_name VARCHAR(32) DEFAULT '',
  6.     pv BIGINT SUM DEFAULT '0'
  7. )
  8. AGGREGATE KEY(site_id, city_code, user_name)
  9. DISTRIBUTED BY HASH(site_id,city_code)
  10. PROPERTIES (
  11.     "replication_num" = "1"
  12. );
复制代码
在实际使用中,可以依据自身的业务特点选择以上两种分桶方式。采用 site_id 的分桶方式对于短查询非常有利,可以大概减少节点之间的数据交换,提高集群整体性能;采用 site_id、city_code 的组合分桶方式对于长查询有利,可以大概利用分布式集群的整体并发性能。
说明:
短查询是指扫描数据量不大、单机就能完成扫描的查询。
长查询是指扫描数据量大、多机并行扫描能显著提升性能的查询。
2.3.4.3 确定分桶数量

在 StarRocks 中,分桶是实际物理文件组织的单元。
 建表时如何设置分桶数量
 方式一:自动设置分桶数量
自 2.5.7 版本起, StarRocks 支持根据机器资源和数据量自动设置分区的分桶数量。
  1. 建表示例:
  2. CREATE TABLE test.site_access13(
  3.     site_id INT DEFAULT '10',
  4.     city_code SMALLINT,
  5.     user_name VARCHAR(32) DEFAULT '',
  6.     pv BIGINT SUM DEFAULT '0'
  7. )
  8. AGGREGATE KEY(site_id, city_code, user_name)
  9. DISTRIBUTED BY HASH(site_id,city_code)
  10. -- 无需手动设置分桶数量
  11. PROPERTIES (
  12.     "replication_num" = "1"
  13. );
复制代码
假如需要开启该功能,则需要确保 FE 动态参数 enable_auto_tablet_distribution 为 true。 建表后,可以实行 SHOW PARTITIONS 来检察 StarRock 为分区自动设置的分桶数量。
  1. SHOW PARTITIONS FROM test.site_access13;
复制代码
 方式二:手动设置分桶数量
自 2.4 版本起,StarRocks 提供了自顺应的 Tablet 并行扫描能力,即一个查询中涉及到的任意一个 Tablet 可能是由多个线程并行地分段扫描,减少了 Tablet 数量对查询能力的限制,从而可以简化对分桶数量的设置。简化后,确定分桶数量方式可以是:起首预估每个分区的数据量,然后按照每 10 GB 原始数据一个 Tablet 计算,从而确定分桶数量。
假如需要开启并行扫描 Tablet,则需要确保体系变量 enable_tablet_internal_parallel 全局见效 SET GLOBAL enable_tablet_internal_parallel = true;。
  1. CREATE TABLE test.site_access14(
  2.     site_id INT DEFAULT '10',
  3.     city_code SMALLINT,
  4.     user_name VARCHAR(32) DEFAULT '',
  5.     pv BIGINT SUM DEFAULT '0')
  6. AGGREGATE KEY(site_id, city_code, user_name)
  7. DISTRIBUTED BY HASH(site_id,city_code) BUCKETS 30
  8. -- 假设导入一个分区的原始数据量为 300 GB,则按照每 10 GB 原始数据一个 Tablet,则分桶数量可以设置为 30。
  9. PROPERTIES (
  10.     "replication_num" = "1"
  11. );
复制代码
 新增分区时如何设置分桶数量
方式一:自动设置分桶数量(推荐)
自 2.5.7 版本起, StarRocks 支持根据机器资源和数据量自动设置分区的分桶数量。
假如需要启用该功能,则需要确保 FE 动态参数 enable_auto_tablet_distribution 保持默认值 true。假如需要关闭该功能,则可以实行ADMIN SET FRONTEND CONFIG (“enable_auto_tablet_distribution” = “false”);并且新增分区的时候未指定分桶数量,则新增分区的分桶数量会继承建表时的分桶数量。 新增分区后,可以实行 SHOW PARTITIONS 来检察 StarRocks 为新增分区自动设置的分桶数量。
方式二:手动设置分桶数量
新增分区的时候,也可以手动指定分桶数量。新增分区的分桶数量的计算方式可以参考如上建表时手动设置分桶数量。
  1. -- 手动创建分区
  2. ALTER TABLE <table_name>
  3. ADD PARTITION <partition_name>
  4.     [DISTRIBUTED BY HASH (k1[,k2 ...]) [BUCKETS num]];
  5.    
  6. -- 手动设置动态分区的默认分桶数量
  7. ALTER TABLE <table_name>
  8. SET ("dynamic_partition.buckets"="xxx");
复制代码
留意:
不支持修改已创建分区的分桶数量。
2.3.5 最佳实践

对于 StarRocks 而言,分区和分桶的选择黑白常关键的。在建表时选择公道的分区键和分桶键,可以有用提高集群整体性能。因此建议在选择分区键和分桶键时,根据业务情况举行调解。
 数据倾斜
假如业务场景中单独采用倾斜度大的列做分桶,很大水平会导致访问数据倾斜,那么建议采用多列组合的方式举行数据分桶。
 高并发
分区和分桶应该只管覆盖查询语句所带的条件,这样可以有用减少扫描数据,提高并发。
 高吞吐
只管把数据打散,让集群以更高的并发扫描数据,完成相应计算。
 元数据管理
控制Tablet数量,因为Tablet 过多会增加 FE/BE 的元数据管理和调理的资源消耗。
2.4 数据压缩

StarRocks 支持对表和索引数据举行压缩 (compression)。数据压缩不仅有助于节流存储空间,还可以提高 I/O 密集型使命的性能。
留意:压缩和解压缩数据需要额外的 CPU 资源。
2.4.1 选择数据压缩算法

StarRocks 支持四种数据压缩算法:LZ4、Zstandard(或 zstd)、zlib 和 Snappy。 这些数据压缩算法在压缩率和压缩/解压缩性能上有所差别。 通常来说,这些算法的压缩率排名如下:zlib > Zstandard > LZ4 > Snappy。其中,zlib 拥有较高的压缩比。但由于数据高度压缩,使用 zlib 算法的表,其导入和查询性能会受到一定水平的影响。而 LZ4 和 Zstandard 算法具有较为平衡的压缩比和解压缩性能。可以根据自身业务场景在这些压缩算法中举行选择,以满足对存储或性能的需求。假如对存储空间占用没有特殊需求,建议使用 LZ4 或 Zstandard 算法。
说明
差别的数据范例也会影响算法的压缩率。
2.4.2 设置数据压缩算法

只能在创建表时为其设置数据压缩算法,且后续无法修改。
以下示例基于 Zstandard 算法创建表 data_compression。
  1. CREATE TABLE test.data_compression(
  2.   `id`      INT(11)     NOT NULL     COMMENT "",
  3.   `name`    CHAR(200)   NULL         COMMENT ""
  4. )
  5. UNIQUE KEY(`id`)
  6. DISTRIBUTED BY HASH(`id`)
  7. PROPERTIES (
  8. "compression" = "ZSTD",
  9. "replication_num" = "1"
  10. );
复制代码
说明
如不指定数据压缩算法,StarRocks 默认使用 LZ4。
可以通过 SHOW CREATE TABLE 命令检察指定表采用的压缩算法。
2.5 排序键和前缀索引

在建表时,可以指定一个或多个列构成排序键 (Sort Key)。表中的行会根据排序键举行排序以后再落入磁盘存储。查询数据时,可以使用排序列指定过滤条件,StarRocks 不需要扫描全表即可快速找到需要处理的数据,降低搜刮的复杂度,从而加速查询。
同时,为减少内存开销,StarRocks 在排序键的根本上又引入了前缀索引 (Prefix Index)。前缀索引是一种稀疏索引。表中每 1024 行数据构成一个逻辑数据块 (Data Block)。每个逻辑数据块在前缀索引表中存储一个索引项,索引项的长度不高出 36 字节,其内容为数据块中第一行数据的排序列组成的前缀,在查找前缀索引表时可以资助确定该行数据所在逻辑数据块的起始行号。前缀索引的巨细会比数据量少 1024 倍,因此会全量缓存在内存中,在实际查找的过程中可以有用加速查询。
2.5.1 排序原理

在明细模型中,排序列就是通过 DUPLICATE KEY 关键字指定的列。
在聚合模型中,排序列就是通过 AGGREGATE KEY 关键字指定的列。
在更新模型中,排序列就是通过 UNIQUE KEY 关键字指定的列。
自 3.0 版本起,主键模型解耦了主键列和排序列,排序列通过 ORDER BY 关键字指定,主键列通过 PRIMARY KEY 关键字指定。
主键模型建表示例:
  1. CREATE TABLE test.site_access_primary
  2. (
  3.     site_id INT DEFAULT '10',
  4.     city_code SMALLINT,
  5.     user_id INT,
  6.     pv BIGINT DEFAULT '0'
  7. )
  8. PRIMARY KEY(site_id)
  9. DISTRIBUTED BY HASH(site_id)
  10. ORDER BY(site_id,city_code)
  11. PROPERTIES (
  12.     "replication_num" = "1"
  13. );
复制代码
在明细模型、聚合模型、更新模型中定义排序列时,需要留意以下几点:
 排序列必须从定义的第一列开始、并且是一连的。
 在定义各列时,计划作为排序列的列必须定义在其他普通列之前。
 排序列的顺序必须与表定义的列顺序同等。
例如,建表语句中声明要创建 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
下面通过示例来说明如何创建使用各个数据模型的表。
2.5.2 排序效果

以上述建表语句为例,排序效果可以分为三种情况:
 假如查询条件只包含 site_id 和 city_code 两列,如下所示,则可以大幅减少查询过程中需要扫描的数据行:
  1. select sum(pv) from test.site_access_duplicate where site_id = 123 and city_code = 2;
复制代码
 假如查询条件只包含 site_id 一列,如下所示,可以定位到只包含 site_id 的数据行:
  1. select sum(pv) from test.site_access_duplicate where site_id = 123;
复制代码
 假如查询条件只包含 city_code 一列,如下所示,则需要扫描全部数据行,排序效果大打折扣:
  1. select sum(pv) from test.site_access_duplicate where city_code = 2;
复制代码
说明
这种情况下,排序列无法实现应有的排序效果。
在第一种情况下,为了定位到数据行的位置,需举行二分查找,以找到指定区间。假如数据行非常多,直接对 site_id 和 city_code 两列举行二分查找,需要把两列数据都加载到内存中,这样会消耗大量的内存空间。这时候可以使用前缀索引来减少缓存的数据量、并有用加速查询。
另外,在实际业务场景中,假如指定的排序列非常多,也会占用大量内存。为了避免这种情况,StarRocks 对前缀索引做了如下限制:
 前缀索引项的内容只能由数据块中第一行的排序列的前缀组成。
 前缀索引列的数量不能高出 3。
 前缀索引项的长度不能高出 36 字节。
 前缀索引中不能包含 FLOAT 或 DOUBLE 范例的列。
 前缀索引中 VARCHAR 范例的列只能出现一次,并且处在末尾位置。
 当前缀索引的末尾列是 CHAR 或 VARCHAR 范例时,前缀索引项的长度不会高出 36 字节。
2.5.3 选择排序列

这里以 site_access_duplicate 表为例,介绍如何选择排序列。
 经常作为查询条件的列,建议选为排序列。
 当排序键涉及多个列的时候,建议把区分度高、且经常查询的列放在前面。区分度高的列是指取值个数较多、且持续增加的列。例如,在上述 site_access_duplicate 表中,因为城市的数目是固定的,所以 city_code 列中取值的个数是固定的,而 site_id 列中取值的个数要比 city_code 列中取值的个数大得多、并且还会不停地增加,所以 site_id 列的区分度就比 city_code 列要高不少。
 排序键不应该包含过多的列。选择很多排序列并不有助于提升查询性能,而且会增大排序的开销,进而增加数据导入的开销。
综上所述,在为 site_access_duplicate 表选择排序列时,需要留意以下三点:
 假如需要经常按 site_id 列加 city_code 列的组合举行查询,建议选择 site_id 列作为排序键的第一列。
 假如需要经常按 city_code 列举行查询、偶然按 site_id 列加 city_code 列的组合举行查询,建议选择 city_code 列作为排序键的第一列。
 极端情况下,假如按 site_id 列加 city_code 列组合查询所占的比例与按 city_code 列单独查询所占的比例半斤八两,可以创建一个以 city_code 列为第一列的 Rollup 表。Rollup 表会为 city_code 列再建一个排序索引 (Sort Index)。
3. 导入导出数据

数据导入是指将原始数据按照业务需求举行清洗、转换、并加载到 StarRocks 中的过程,从而可以在 StarRocks 体系中举行极速同一的数据分析。
具体详见:
  1. https://docs.starrocks.io/zh/docs/loading/Loading_intro/
复制代码
另外,StarRocks也支持导出数据,可以通过 EXPORT 语句把 StarRocks 集群中指定表或分区上的数据以 CSV 的格式导出到外部存储体系。
  1. 具体详见:https://docs.starrocks.io/zh/docs/unloading/Export/
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

不到断气不罢休

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表