前言
在大数据时代,如何让海量数据的查询"快如闪电",一直是数据领域最核心的挑战之一。从早期的Hive离线批处理,到Kylin的预计算,再到ClickHouse的向量化引擎,每一步演进都在追求更快的查询速度。而今天要介绍的 StarRocks,作为新一代MPP数据库,正在以惊人的性能表现重新定义OLAP查询的极限。
一、StarRocks 是什么?
StarRocks(原DorisDB)是一款高性能、全场景的MPP分析型数据库,支持实时、批量和交互式等多种数据分析场景。它的核心设计理念是:让用户用最简单的方式,获得最快的查询体验。
简单来说,StarRocks 能做到:
- 毫秒到秒级返回海量数据的查询结果
- 同时支持实时数据接入 和离线批量导入
- 兼容 MySQL 协议,开箱即用
- 无需预建物化视图,无需建模即可获得极速查询
二、核心架构
StarRocks 采用经典的 MPP(Massively Parallel Processing)架构,主要由两类进程组成:
2.1 FE(Frontend)- 前端节点
FE 是 StarRocks 的"大脑",负责:
- 查询解析与优化:SQL解析、逻辑计划生成、CBO优化
- 元数据管理:数据库、表、分区等元信息的存储和管理
- 查询调度:将查询计划分发到BE节点执行
- 节点管理:集群中FE/BE节点的状态监控
FE 之间通过 BDBJE 实现主备高可用,确保元数据不丢失。
2.2 BE(Backend)- 后端节点
BE 是 StarRocks 的"肌肉",负责:
- 数据存储:列式存储,支持分区、分桶、压缩
- 查询执行:向量化执行引擎,充分利用CPU缓存
- 数据导入:支持Stream Load、Broker Load、Routine Load等多种方式
BE 之间无共享(Shared-Nothing),数据按分桶分布在不同BE上,查询时并行执行。
2.3 架构图
┌─────────────────────────────────────────────┐
│ Client │
│ (MySQL Client / JDBC / ODBC) │
└──────────────────┬──────────────────────────┘
│ MySQL Protocol
┌──────────────────▼──────────────────────────┐
│ FE (Frontend) │
│ ┌─────────┐ ┌──────────┐ ┌───────────┐ │
│ │ SQL解析 │→│ 查询优化 │→│ 查询调度 │ │
│ └─────────┘ └──────────┘ └───────────┘ │
│ ┌─────────┐ ┌──────────┐ │
│ │ 元数据 │ │ 节点管理 │ │
│ └─────────┘ └──────────┘ │
└────────┬─────────────┬──────────────────────┘
│ │
┌────▼───┐ ┌────▼───┐ ┌────────┐
│ BE 1 │ │ BE 2 │ │ BE N │
│┌──────┐│ │┌──────┐│ │┌──────┐│
││数据1 ││ ││数据2 ││ ││数据N ││
│└──────┘│ │└──────┘│ │└──────┘│
└────────┘ └────────┘ └────────┘
三、为什么 StarRocks 这么快?
StarRocks 的性能优势并非来自单一技术,而是多个层面的深度优化叠加:
3.1 向量化执行引擎
这是 StarRocks 性能的基石。传统数据库一次处理一行(Row-at-a-time),而向量化引擎一次处理一批数据(Column-at-a-time),大幅减少虚函数调用和分支预测失败,同时充分利用CPU的SIMD指令集。
python
# 传统行存执行: 每行一次函数调用
for row in rows:
result = filter(row.price > 100) # 每行一次比较
# 向量化执行: 整列一次操作
prices = column("price") # 连续内存
mask = prices > 100 # SIMD并行比较
result = apply_mask(prices, mask) # 批量处理
3.2 CBO 优化器(Cost-Based Optimizer)
StarRocks 自研了基于Cascades框架的CBO优化器,能够:
- 多表Join自动选择最优执行顺序:无需人工调整Join顺序
- 智能选择Join策略:Hash Join、Merge Join、Nest Loop Join
- 动态调整执行计划:基于运行时统计信息自适应优化
对于多表关联查询,CBO优化器可以带来数倍甚至数十倍的性能提升。
3.3 物化视图(Materialized View)
StarRocks 支持自动维护的物化视图,无需用户手动刷新:
sql
-- 创建物化视图,自动聚合
CREATE MATERIALIZED VIEW mv_daily_sales
AS
SELECT
dt,
product_id,
SUM(amount) AS total_amount,
COUNT(*) AS order_count
FROM sales
GROUP BY dt, product_id;
-- 查询时自动路由到物化视图,无需改写SQL
SELECT dt, SUM(amount)
FROM sales
WHERE dt = '2024-01-01'
GROUP BY dt;
-- ↑ 自动命中 mv_daily_sales,无需全表扫描
3.4 智能分区分桶
- 分区:按时间等维度将数据物理隔离,查询时自动裁剪无关分区
- 分桶:将数据均匀分布到不同BE节点,实现并行扫描
sql
CREATE TABLE sales (
id BIGINT,
dt DATE,
product_id INT,
amount DECIMAL(10,2)
)
PARTITION BY RANGE(dt) (
FROM ('2024-01-01') TO ('2024-02-01') INTERVAL 1 DAY
)
DISTRIBUTED BY HASH(id) BUCKETS 8;
3.5 Global Runtime Filter
在多表Join场景下,StarRocks 会在运行时动态构建Bloom Filter,将小表的Join Key下推到大表的扫描阶段,提前过滤无关数据,大幅减少数据传输和计算量。
大表扫描 ──────┐
├─→ Hash Join ─→ 结果
小表扫描 ──┬──→┘
│
构建Runtime Filter
(Bloom Filter / Min-Max)
│
↓ 下推到大表扫描端
大表扫描时提前过滤 90%+ 无效数据
四、核心特性详解
4.1 多数据模型支持
StarRocks 支持四种表模型,覆盖不同业务场景:
| 模型 | 适用场景 | 特点 |
|---|---|---|
| Duplicate Key | 明细数据、日志 | 数据原样保留,不做聚合 |
| Aggregate Key | 报表、预聚合 | 同Key数据自动聚合(REPLACE/SUM/MAX/MIN) |
| Unique Key | 订单、用户画像 | 同Key数据保留最新值 |
| Primary Key | 实时更新场景 | 支持高频更新,读时合并 |
4.2 实时数据接入
StarRocks 支持多种实时数据导入方式:
Stream Load - HTTP推送,适合微秒级延迟:
bash
curl --location-trusted -u user:passwd \
-H "column_separator:," \
-T data.csv \
http://fe_host:8030/api/db/table/_stream_load
Routine Load - 持续消费Kafka:
sql
CREATE ROUTINE LOAD load_kafka
ON TABLE sales
COLUMNS TERMINATED BY ","
PROPERTIES (
"desired_concurrent_number" = "3"
)
FROM KAFKA (
"kafka_broker_list" = "kafka:9092",
"kafka_topic" = "sales_topic"
);
Flink Connector - 流批一体:
java
StarRocksSink.sink(
StarRocksSinkOptions.builder()
.withProperty("jdbc-url", "jdbc:mysql://fe:9030")
.withProperty("table-name", "sales")
.build()
);
4.3 多 catalogs 统一查询
StarRocks 支持直接查询外部数据源,无需数据搬迁:
sql
-- 查询Hive数据
CREATE CATALOG hive_catalog WITH (
type = 'hive',
hive.metastore.uris = 'thrift://metastore:9083'
);
SELECT * FROM hive_catalog.dw.fact_sales;
-- 联邦查询: StarRocks表 JOIN Hive表
SELECT a.user_id, b.user_name
FROM starrocks_db.orders a
JOIN hive_catalog.dw.users b
ON a.user_id = b.user_id;
支持的外部数据源包括:
- Apache Hive
- Apache Iceberg
- Apache Hudi
- Delta Lake
- Elasticsearch
- JDBC(MySQL/PostgreSQL等)
五、实战:从0到1搭建数据分析平台
5.1 集群部署
最简部署(1FE + 3BE):
yaml
# docker-compose.yml
version: '3'
services:
fe:
image: starrocks/fe-ubuntu:3.2
ports:
- "9030:9030" # MySQL协议
- "8030:8030" # HTTP
environment:
- FE_SERVERS=fe:9010
- FE_ID=1
be1:
image: starrocks/be-ubuntu:3.2
depends_on:
- fe
environment:
- FE_SERVERS=fe:9010
be2:
image: starrocks/be-ubuntu:3.2
depends_on:
- fe
environment:
- FE_SERVERS=fe:9010
be3:
image: starrocks/be-ubuntu:3.2
depends_on:
- fe
environment:
- FE_SERVERS=fe:9010
5.2 建表与导入
sql
-- 1. 创建数据库
CREATE DATABASE analytics;
USE analytics;
-- 2. 创建事实表(Primary Key模型,支持实时更新)
CREATE TABLE orders (
order_id BIGINT,
user_id BIGINT,
product_id INT,
amount DECIMAL(10,2),
status VARCHAR(20),
create_time DATETIME,
update_time DATETIME
)
PRIMARY KEY (order_id)
PARTITION BY RANGE(create_time) (
FROM ('2024-01-01') TO ('2025-01-01') INTERVAL 1 MONTH
)
DISTRIBUTED BY HASH(order_id) BUCKETS 16
PROPERTIES (
"replication_num" = "3",
"enable_persistent_index" = "true"
);
-- 3. 创建维度表
CREATE TABLE products (
product_id INT,
product_name VARCHAR(100),
category VARCHAR(50),
brand VARCHAR(50)
)
UNIQUE KEY (product_id)
DISTRIBUTED BY HASH(product_id) BUCKETS 4;
-- 4. 导入数据
INSERT INTO orders VALUES
(1001, 5001, 101, 299.00, 'PAID', '2024-03-15 10:30:00', '2024-03-15 10:30:00'),
(1002, 5002, 102, 199.00, 'SHIPPED', '2024-03-15 11:00:00', '2024-03-15 14:00:00'),
(1003, 5001, 103, 599.00, 'PAID', '2024-03-15 12:00:00', '2024-03-15 12:00:00');
5.3 典型查询场景
sql
-- 场景1: 实时大屏 - 今日GMV
SELECT
DATE(create_time) AS dt,
COUNT(*) AS order_count,
SUM(amount) AS gmv
FROM orders
WHERE create_time >= CURRENT_DATE()
GROUP BY DATE(create_time);
-- 场景2: 用户行为分析 - 复购率
SELECT
user_id,
COUNT(*) AS purchase_count,
COUNT(DISTINCT DATE(create_time)) AS active_days,
SUM(amount) AS total_amount
FROM orders
WHERE create_time >= DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)
GROUP BY user_id
HAVING purchase_count > 1
ORDER BY total_amount DESC
LIMIT 100;
-- 场景3: 多表关联 - 品类销售排行
SELECT
p.category,
p.brand,
COUNT(*) AS order_count,
SUM(o.amount) AS total_sales
FROM orders o
JOIN products p ON o.product_id = p.product_id
WHERE o.create_time >= DATE_SUB(CURRENT_DATE(), INTERVAL 7 DAY)
GROUP BY p.category, p.brand
ORDER BY total_sales DESC;
六、性能调优最佳实践
6.1 建表优化
sql
-- 合理选择分区分桶
-- 分区: 按查询最常用的过滤条件(通常是时间)
-- 分桶: 按Join/Group By最常用的列,且基数适中
CREATE TABLE fact_order (
order_id BIGINT,
dt DATE,
user_id BIGINT,
...
)
PARTITION BY RANGE(dt) (
FROM ('2024-01-01') TO ('2025-01-01') INTERVAL 1 DAY -- 按天分区
)
DISTRIBUTED BY HASH(user_id) BUCKETS 32; -- 按user_id分桶,利于Join
-- 开启列存索引(Column Index),加速点查
PROPERTIES (
"enable_persistent_index" = "true" -- Primary Key表
);
6.2 查询优化
sql
-- 1. 利用分区裁剪
-- 好: 指定分区列条件
SELECT * FROM orders WHERE dt = '2024-03-15';
-- 差: 全表扫描
SELECT * FROM orders WHERE amount > 100;
-- 2. 利用Profile分析慢查询
SET enable_profile = true;
SELECT ... ; -- 执行查询
SHOW QUERY PROFILE 'xxx'; -- 查看执行计划详情
-- 3. 合理使用Bitmap索引(低基数字段)
ALTER TABLE orders ADD INDEX idx_status (status) USING BITMAP;
-- 4. 大表Join使用Colocate Group
-- 将经常Join的表放在同一分桶分布
CREATE COLOCATE GROUP order_group (
orders DISTRIBUTED BY HASH(user_id) BUCKETS 32,
user_actions DISTRIBUTED BY HASH(user_id) BUCKETS 32
);
6.3 导入优化
sql
-- 批量导入时关闭自动合并,提升写入速度
PROPERTIES (
"disable_auto_compaction" = "true" -- 导入高峰期临时关闭
);
-- Stream Load开启并行导入
curl ... -H "load_parallelism:8" ...
-- 合理设置compaction策略
ALTER SYSTEM SET base_compaction_num_cumulative_deltas = 5;
七、StarRocks vs ClickHouse vs Doris
| 维度 | StarRocks | ClickHouse | Apache Doris |
|---|---|---|---|
| 查询性能 | 多表Join极强 | 单表扫描极强 | 均衡 |
| 多表Join | CBO优化,表现优异 | 依赖手动优化 | 支持但优化有限 |
| 实时更新 | Primary Key模型,原生支持 | Mutations,较重 | Unique Key模型 |
| 数据更新 | 支持高频部分列更新 | 需Replace整行 | 支持但性能一般 |
| 物化视图 | 自动维护,查询自动路由 | 手动刷新 | 自动维护 |
| 联邦查询 | 多Catalog,支持Hive/Iceberg等 | 有限支持 | 有限支持 |
| 运维复杂度 | 中等 | 较高 | 中等 |
| 社区生态 | 快速增长 | 成熟 | Apache顶级项目 |
选型建议:
- 单表大宽表 + 聚合查询 → ClickHouse
- 多表Join + 实时更新 + 联邦查询 → StarRocks
- 已有Doris集群 + 平稳运行 → 继续用Doris
- 新项目 + 需要全场景 → StarRocks
八、典型应用场景
8.1 实时数仓
业务DB(Canal/Debezium) → Flink → StarRocks
↓
实时报表/大屏
8.2 OLAP分析平台
Hive离线数仓 → StarRocks External Catalog → 统一查询入口
实时数据流 → StarRocks Internal Table ↓
BI工具/Ad-hoc查询
8.3 用户画像与推荐
用户行为日志 → Kafka → Routine Load → StarRocks
↓
用户画像标签表 ←→ 推荐系统
九、总结
StarRocks 的核心优势可以总结为三点:
- 快:向量化引擎 + CBO优化器 + Runtime Filter,多表Join场景性能领先
- 简:兼容MySQL协议,支持联邦查询,减少数据搬运
- 全:实时+离线、明细+聚合、内表+外表,一套系统覆盖全场景
如果你正在构建新一代数据分析平台,StarRocks 值得认真评估。它不是银弹,但在"多表关联 + 实时查询"这个核心战场上,目前确实是最强的选择之一。
参考资料: