我们用StarRocks做数据分析,最开始查询很慢,经过一系列优化,性能提升了10倍。
StarRocks是一个高性能的分析型数据库,主打亚秒级查询。但如果用不好,性能也会很差。本文分享StarRocks性能优化的实战经验,包括表设计优化、分区分桶优化、数据模型选择、索引优化、SQL优化、资源配置、监控调优,以及踩过的坑和经验总结。
一、背景
1. 为什么选StarRocks
我们之前用的是ClickHouse,性能不错,但有几个问题:
- 多表关联性能差
- 不支持标准SQL,学习成本高
- 并发能力弱
- 运维复杂
后来调研了StarRocks,发现它:
- 兼容MySQL协议,学习成本低
- 多表关联性能好(CBO优化器)
- 并发能力强
- 支持实时更新
- 运维相对简单
于是,我们把数据分析平台迁移到了StarRocks。
2. 遇到的问题
迁移之后,最开始性能很差:
- 简单查询要几秒
- 复杂查询要几十秒甚至几分钟
- 并发上不去,几个查询就卡
- 数据导入慢
- 资源占用高
我们花了一个月时间优化,性能提升了10倍。本文分享优化过程。
二、表设计优化
表设计,是StarRocks性能优化的基础。表设计不好,后面怎么优化都没用。
1. 数据模型选择
StarRocks有三种数据模型:
- 明细模型(Duplicate Key):保留所有明细数据,适合原始数据存储
- 聚合模型(Aggregate Key):按Key聚合,适合预聚合场景
- 更新模型(Unique Key):按Key更新,适合需要更新的场景
选择建议:
- 原始数据、日志数据:用明细模型
- 汇总数据、报表数据:用聚合模型
- 需要更新的数据:用更新模型
我们最开始所有表都用明细模型,查询的时候再聚合,性能很差。后来把常用的汇总表改成聚合模型,查询性能提升了3-5倍。
2. 排序键(Sort Key)
StarRocks的数据是按排序键排序存储的,排序键的选择很重要。
排序键的原则:
- 把常用的过滤条件字段放在前面
- 把等值查询的字段放在前面
- 把高基数的字段放在前面
- 排序键的前3个字段最重要
比如,我们有一张订单表,常用的过滤条件是日期和用户ID。我们把排序键设为(dt, userid, orderid),查询的时候按日期和用户ID过滤,性能很好。
如果排序键设错了,比如把order_id放在前面,查询的时候按日期过滤,就会全表扫描,性能很差。
3. 字段类型选择
字段类型,对性能也有影响。
- 尽量用小的数据类型:能用TINYINT就不用INT,能用INT就不用BIGINT
- 字符串类型:VARCHAR比STRING好,尽量控制长度
- 日期类型:用DATE或DATETIME,不要用字符串
- 避免用FLOAT/DOUBLE做关联键,精度问题
我们有一张表,把日期存成了VARCHAR,查询的时候做类型转换,性能很差。改成DATE类型之后,性能提升了2倍。
三、分区分桶优化
1. 分区(Partition)
分区是StarRocks性能优化的重要手段。
分区的原则:
- 按时间分区:最常用,按天或按月分区
- 分区数量:单表分区数建议不超过1000
- 分区大小:每个分区建议100GB以内
- 动态分区:可以配置自动创建和删除分区
我们的表都是按天分区,查询的时候指定日期,只扫描对应分区,性能很好。
如果不分区,查询就会全表扫描,性能很差。
2. 分桶(Bucket)
分桶决定了数据在节点之间的分布。
分桶的原则:
- 分桶列:选择高基数的列,如用户ID、订单ID
- 分桶数量:根据数据量和节点数确定
- 每个分桶的大小:建议1-10GB
- 分桶数量一旦确定,不能修改
分桶数量的经验公式:
- 数据量 / 每个分桶大小 = 分桶数量
- 分桶数量应该是节点数的整数倍
我们有一张表,最开始只分了4个桶,数据量很大,每个桶几十GB,查询很慢。后来改成32个桶,每个桶几GB,查询性能提升了3倍。
3. 动态分区
StarRocks支持动态分区,可以自动创建和删除分区。
配置示例:
PROPERTIES (
"dynamic_partition.enable" = "true",
"dynamic_partition.time_unit" = "DAY",
"dynamic_partition.start" = "-30",
"dynamic_partition.end" = "3",
"dynamic_partition.prefix" = "p",
"dynamic_partition.buckets" = "32"
);这样,StarRocks会自动创建未来3天的分区,自动删除30天前的分区。不用手动管理分区了。
四、索引优化
1. 前缀索引
StarRocks默认有前缀索引,基于排序键的前36个字节。
前缀索引的原理:
- 数据按排序键排序
- 每1024行数据,建立一个前缀索引项
- 查询的时候,先用前缀索引定位到大概位置,再精确查找
用好前缀索引的关键:
- 排序键的前几个字段,要是常用的过滤条件
- 等值查询的字段,尽量放在排序键前面
- 避免在排序键前面用范围查询(会导致后面的字段用不上前缀索引)
2. Bitmap索引
对于低基数的列(如性别、状态、类型),可以建Bitmap索引。
CREATE INDEX idx_status ON table_name(status) USING BITMAP;Bitmap索引适合:
- 低基数列(几个到几十个不同值)
- 常用的过滤条件
- 多条件组合查询
我们有一张表,status字段只有几个值,建了Bitmap索引之后,按status过滤的查询性能提升了5倍。
3. Bloom Filter索引
对于高基数的列(如用户ID、订单ID),可以建Bloom Filter索引。
PROPERTIES (
"bloom_filter_columns" = "user_id, order_id"
);Bloom Filter适合:
- 高基数列
- 等值查询
- 非排序键的列
我们有一张表,userid不是排序键,但经常用userid做等值查询。建了Bloom Filter之后,查询性能提升了2倍。
五、SQL优化
1. 用EXPLAIN分析执行计划
SQL慢,第一步是用EXPLAIN看执行计划。
EXPLAIN SELECT * FROM orders WHERE dt = '2022-10-01' AND user_id = 123;看执行计划,重点关注:
- 扫描了多少分区
- 扫描了多少行
- 有没有用上索引
- Join的顺序和方式
- 有没有数据倾斜
2. 避免SELECT *
不要用SELECT *,只查需要的字段。
StarRocks是列式存储,只查需要的列,可以减少IO。
-- 不好
SELECT * FROM orders;
-- 好
SELECT order_id, user_id, amount FROM orders;3. 过滤条件下推
尽量把过滤条件写在WHERE里,让StarRocks尽早过滤数据。
- 分区裁剪:指定分区字段,只扫描需要的分区
- 前缀索引:过滤条件用上排序键
- Bitmap/Bloom Filter:过滤条件用上索引
4. Join优化
多表关联,是StarRocks的强项,但也要注意:
- 小表在前,大表在后
- 用等值关联,不要用不等值关联
- 关联键尽量用整数类型
- 避免大表关联大表
- 可以用Broadcast Join(小表广播到所有节点)
StarRocks的CBO优化器会自动选择Join策略,但如果统计信息不准,可能选错。可以用ANALYZE TABLE更新统计信息。
5. 聚合优化
聚合查询,注意:
- 尽量用聚合模型的表,预聚合数据
- GROUP BY的字段,尽量用排序键
- 避免在聚合函数里用复杂表达式
- 可以用物化视图预计算常用聚合
6. 避免在WHERE里用函数
不要在WHERE里对字段用函数,会导致索引用不上。
-- 不好
SELECT * FROM orders WHERE DATE(create_time) = '2022-10-01';
-- 好
SELECT * FROM orders WHERE create_time >= '2022-10-01' AND create_time < '2022-10-02';六、物化视图
物化视图,是StarRocks的一大利器。
1. 什么是物化视图
物化视图,就是把常用的查询结果预先计算好,存起来。查询的时候直接读物化视图,不用重新计算。
比如,我们经常按天统计销售额,可以建一个物化视图:
CREATE MATERIALIZED VIEW mv_daily_sales AS
SELECT dt, SUM(amount) as total_amount
FROM orders
GROUP BY dt;查询的时候,StarRocks会自动路由到物化视图,性能提升很多。
2. 物化视图的适用场景
- 常用的聚合查询
- 多表关联的查询
- 报表查询
- 固定维度的统计
3. 注意事项
- 物化视图会占用存储空间
- 数据导入的时候,会同步更新物化视图,影响导入性能
- 不要建太多物化视图,维护成本高
- 定期检查物化视图是否被使用
我们建了几个常用报表的物化视图,报表查询性能提升了5-10倍。
七、资源配置优化
1. 节点配置
StarRocks的节点,分为FE(Frontend)和BE(Backend)。
- FE:管理元数据,执行SQL解析和优化。建议3个节点,保证高可用。
- BE:存储数据,执行查询。根据数据量和并发量确定节点数。
BE节点的配置建议:
- CPU:16核以上
- 内存:64GB以上
- 磁盘:SSD,NVMe更好
- 网络:万兆网卡
2. 内存配置
BE的内存配置很重要。
mem_limit:BE进程可用内存比例,建议80%querymemlimit:单个查询的内存限制,根据查询大小调整loadmemlimit:导入的内存限制
内存不够,查询会 spill 到磁盘,性能急剧下降。要保证内存充足。
3. 并发控制
StarRocks的并发控制:
queryqueueconcurrency_limit:查询队列的并发限制queryqueuememusedpct_limit:内存使用比例限制maxqueryretry_time:查询重试次数
根据服务器配置,合理设置并发数。并发太高,会导致资源争抢,性能反而下降。
4. 导入优化
数据导入的优化:
- 用Stream Load或Broker Load
- 批量导入,每次导入的数据量不要太小
- 控制导入并发,避免影响查询
- 合理设置导入的内存限制
我们最开始是一条条导入,性能很差。改成批量导入之后,导入性能提升了10倍。
八、监控和调优
1. 监控指标
StarRocks的监控,重点关注:
- 查询延迟:P50、P95、P99
- 查询并发:当前查询数
- 导入延迟:导入的耗时
- 存储使用:磁盘使用率
- 内存使用:BE内存使用率
- CPU使用:CPU使用率
- 慢查询:超过阈值的查询
2. 慢查询分析
定期分析慢查询:
- 开启慢查询日志
- 每天分析慢查询
- 对慢查询做优化
- 优化后验证效果
我们建立了慢查询分析机制,每天花半小时分析慢查询,逐个优化,整体性能持续提升。
3. 统计信息更新
StarRocks的CBO优化器依赖统计信息。统计信息不准,优化器可能选错执行计划。
定期更新统计信息:
ANALYZE TABLE table_name;建议:
- 每天更新一次统计信息
- 数据量大变化后,手动更新
- 重点更新常用查询的表
九、踩过的坑
坑一:分桶数量不对
我们有一张表,分桶数量太少,数据倾斜严重,查询很慢。
后来重新建表,调整了分桶数量,查询性能提升了3倍。
教训:分桶数量要根据数据量确定,不能随便设。
坑二:排序键设错
我们有一张表,排序键设错了,常用的过滤字段不在排序键前面,查询全表扫描。
后来重新建表,调整了排序键,查询性能提升了5倍。
教训:排序键是StarRocks性能的关键,设之前要想清楚查询模式。
坑三:数据模型选错
我们有一张汇总表,最开始用了明细模型,查询的时候再聚合,性能很差。
改成聚合模型之后,查询性能提升了4倍。
教训:根据查询模式选择数据模型,汇总表用聚合模型。
坑四:并发太高
我们最开始把并发设得很高,结果查询互相争抢资源,整体性能很差。
后来降低了并发,反而整体吞吐量提升了。
教训:并发不是越高越好,要根据服务器配置合理设置。
坑五:统计信息不准
有一次,一个简单的查询突然变得很慢。查了半天,发现是统计信息过期了,优化器选错了执行计划。
更新统计信息之后,查询恢复正常。
教训:定期更新统计信息,数据变化大的时候要手动更新。
十、优化效果
经过一个月的优化,效果很明显:
- 简单查询:从3-5秒降到100-300毫秒
- 复杂查询:从30-60秒降到3-5秒
- 并发能力:从5个并发就卡,提升到50个并发没问题
- 导入性能:从每秒几百条,提升到每秒几万条
- 资源使用:CPU和内存使用率更合理了
整体性能提升了10倍左右。
十一、经验总结
1. 表设计是基础
StarRocks的性能,70%取决于表设计。
- 选对数据模型
- 设对排序键
- 合理分区和分桶
- 选对字段类型
表设计好了,性能就不会差。表设计不好,后面怎么优化都没用。
2. 索引是利器
合理使用索引,能大幅提升查询性能。
- 前缀索引:默认就有,用好排序键
- Bitmap索引:低基数列
- Bloom Filter:高基数列的等值查询
3. SQL要写好
SQL写得好不好,对性能影响很大。
- 用EXPLAIN分析执行计划
- 避免SELECT *
- 过滤条件下推
- 优化Join和聚合
- 避免在WHERE里用函数
4. 物化视图要巧用
物化视图是StarRocks的一大利器,常用的聚合查询,建物化视图,性能提升明显。
- 不要建太多
- 定期检查是否被使用
- 注意对导入性能的影响
5. 资源要配够
StarRocks对资源要求比较高。
- CPU、内存、磁盘、网络,都要够
- 内存尤其重要,不够会 spill 到磁盘
- 合理设置并发,不是越高越好
6. 监控要跟上
- 建立完善的监控
- 定期分析慢查询
- 定期更新统计信息
- 持续优化,性能才能持续提升
十二、写在最后
StarRocks是一个很棒的分析型数据库,性能很强,但要用好它,需要花时间学习和优化。
我们从最开始的查询很慢,到后来的亚秒级响应,花了一个月时间。优化的过程,也是学习的过程。表设计、索引、SQL、物化视图、资源配置、监控,每一个环节都很重要。
2022年了,StarRocks发展很快,社区活跃,功能越来越完善。如果你在做数据分析,可以试试StarRocks,它可能会给你带来惊喜。
最后,用一句话总结:"StarRocks性能优化,表设计是基础,索引是利器,SQL要写好,物化视图要巧用,资源要配够,监控要跟上。做好这几点,性能自然就上去了。"
愿你的StarRocks查询,又快又稳。
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录