Starrocks优化---持续更新

79 阅读2分钟

1.优化大表JOIN

(1) 使用广播JOIN(Broadcast Join)

适用于小表join大表 当一个表较小(通常小于1GB)时,可以通过将小表广播到所有计算节点来优化

 SELECT /*+ BROADCAST(dim_table) */  
 f.order_id, f.user_id, d.user_name 
 FROM fact_orders f  
 JOIN dim_table d 
 ON f.user_id = d.user_id 
 WHERE f.order_time > '2023-01-01'

(2) 使用 Colocate Join(CG)

适用于大表join大表

前提:分桶键和数量必须一致,副本数一致

底层原理:同一 CG 内的表数据分片(Tablet)会分布在相同的 BE(Backend)节点上,确保相同分桶键的数据在物理上相邻存储, 那么当 Join 的列是分桶键时,StarRocks 可以直接在本地节点进行 Join,无需跨节点传输数据。

例如:

  • 表 A表 B 的分桶键均为 user_id,且属于同一 CG。
  • 对于 user_id = 100 的数据,表 A 的 Bucket 0 和表 B 的 Bucket 0 均存储在 BE 节点 A 上,Join 操作直接在节点 A 完成

两次映射机制

  1. 分桶键到分桶编号:通过哈希分桶键并取模分桶数,确定数据所属的分桶。
  2. 分桶编号到 BE 节点:通过固定映射策略(如 Round Robin)将分桶分配到具体的 BE 节点

当需要频繁JOIN两个大表时,使用Colocate Join 可以减少数据传输:

-- 创建Colocate组
CREATE COLOCATE GROUP group1;

-- 创建表时指定Colocate组,确保JOIN键分布一致
CREATE TABLE orders ( 
  order_id BIGINT,   
  user_id BIGINT,    
  order_time DATETIME,    
  amount DECIMAL(102)
) ENGINE=OLAP
DUPLICATE KEY(order_id)
DISTRIBUTED BY HASH(user_id) BUCKETS 8
PROPERTIES (    
  "colocate_with" = "group1"
);

CREATE TABLE users (   
  user_id BIGINT,   
  user_name VARCHAR(50),   
  register_time DATETIME
) ENGINE=OLAP
DUPLICATE KEY(user_id)
DISTRIBUTED BY HASH(user_id) BUCKETS 8
PROPERTIES (    
  "colocate_with" = "group1"
);

(3) 优化 JOIN 条件

在JOIN前增加过滤条件,减少JOIN的数据量

SELECT f.order_id, f.user_id, d.user_name
FROM fact_orders f 
JOIN (   
  SELECT user_id, user_name     
  FROM dim_table    
  WHERE region = 'ASIA')
  d ON f.user_id = d.user_id
  WHERE f.order_time > '2023-01-01';

(4) 使用物化视图预聚合

-- 创建物化视图
CREATE MATERIALIZED VIEW mv_order_summary
DISTRIBUTED BY HASH(user_id)
REFRESH ASYNC
AS SELECT    
    user_id,    
    COUNT(*as order_count,    
    SUM(amount) as total_amount
FROM orders
GROUP BY user_id;

-- 使用物化视图进行JOIN
SELECT 
  m.user_id,
  u.user_name, 
  m.order_count,
  m.total_amount
FROM mv_order_summary m
JOIN users u 
ON m.user_id = u.user_id;

(5) 合理设计JOIN顺序

使用/*+ LEADING */ 提示指定JOIN顺序

SELECT /*+ LEADING(f d1 d2) */    
  f.order_id, d1.user_name, d2.product_name
FROM fact_orders f
JOIN dim_users d1 
  ON f.user_id = d1.user_id
JOIN dim_products d2 
  ON f.product_id = d2.product_id
WHERE f.order_time > '2023-01-01';