Boopathi G
04/29/2026, 8:21 AMRocky
04/29/2026, 8:22 AMDISTRIBUTED BY HASH(cm_id) creates a rigid mapping where every row for a specific cm_id is assigned the same hash value and, therefore, must reside in the exact same bucket (tablet) on one BE. This is the physical requirement for a Colocate Join, but it effectively turns your largest whale customers into "single-node" databases.
To resolve this while keeping joins fast, you have two StarRocks-native paths:
Solution 1: The "Hybrid" View (Recommended for Performance)
This approach allows you to keep Colocate Join for 99% of your customers (small/medium) while splitting the whales across the cluster to balance storage and RAM.
1. Split the data into two tables:
* `table_main`: Distributed by HASH(cm_id) and part of the colocate_with group. Contains all standard customers.
* `table_whales`: Distributed by HASH(cm_id, id) (or RANDOM in v3.1+). This splits the whale's data across all 3 BEs.
2. Create a Unified View:
sql
CREATE VIEW customer_data AS
SELECT * FROM table_main
UNION ALL
SELECT * FROM table_whales;
3. Why this works:
* Small Customers: Joins on cm_id will prune to table_main. StarRocks will use the Colocate Join strategy, keeping queries sub-second.
* Whale Customers: Joins will prune to table_whales. Because the data is balanced across all nodes, StarRocks will use a Shuffle Join or Bucket Shuffle Join. While not a "local join," the parallel compute power of all 3 BEs working on the whale's data is usually faster than one BE struggling with a 38GB tablet.
──────────
Solution 2: Skew Join V2 (Recommended for Scalability)
If you prefer a single table, you must change the distribution key to balance storage, and then use StarRocks' Skew Join V2 (available in v3.x) to handle the join performance.
1. Rebalance Storage:
Modify the table to use a composite hash key: DISTRIBUTED BY HASH(cm_id, some_id). This will immediately solve your storage skew (the 38GB tablet will be split into smaller pieces across all BEs) and stop the Routine Load OOMs.
2. Optimize the Join:
Since a join on cm_id is no longer "Colocated," StarRocks would normally perform a standard Shuffle Join. To optimize this for whales, use the Skew Join V2 hint:
sql
SELECT /_+ SKEW_JOIN(t1, cm_id(1001)) _/ *
FROM table1 t1
JOIN table2 t2 ON t1.cm_id = t2.cm_id;
* Hint Syntax: You explicitly tell the optimizer that cm_id = 1001 is a whale.
* Native Logic: StarRocks will use a Broadcast Join specifically for that value (broadcasting the small side of the join to all nodes) and a Shuffle Join for everything else. This prevents the single-BE bottleneck during query execution.
──────────
Why Routine Load is OOMing
The OOM on BE-0 is occurring because when you load data for the whale customer, the Coordinator BE must send all that data to the one BE that owns that specific bucket. That BE then has to process a massive amount of data in memory (indexing, sorting, and building rowsets) for a single tablet.
* Fix: By changing to HASH(cm_id, id), the load task is distributed. Instead of one BE receiving 100% of the whale's load, each BE receives ~33%, staying well within RAM limits.
Summary of Actions
* Immediate fix for OOM: Alter the table to DISTRIBUTED BY HASH(cm_id, id) BUCKETS 48 (roughly 16 buckets per BE).
* If you must have Colocate Join for small tenants: Use the Solution 1 (View) approach.
* If you prioritize schema simplicity: Use Solution 2 (Skew Join V2) and enable it globally with SET enable_optimize_skew_join_v2 = true;.
Note: Avoid increasing the bucket count (e.g., to 128) while keeping HASH(cm_id). It will not help; a single cm_id will still map to exactly one bucket regardless of how many buckets exist.
References