Alejandro De La Hoz
05/05/2026, 12:26 AMRocky
05/05/2026, 12:26 AMcache-dict thread pool, usually points to issues with the Global Dictionary (Low Cardinality Optimization) mechanism.
1. Understanding the cache-dict Thread Pool
The cache-dict thread pool in StarRocks is responsible for loading and refreshing Global Dictionaries from the Backend (BE) nodes into the FE's memory.
* What it does: When the optimizer decides to use low-cardinality optimization (encoding string columns as integers), the FE must fetch the dictionary to perform plan rewriting.
* Saturation: If you see "rejected execution" logs for the cache-dict pool, it means the FE is trying to load too many dictionaries simultaneously, exceeding the pool's capacity (which is often fixed at 16 threads in some versions).
* Memory Impact: These dictionaries are cached in the FE heap. If your workload involves many tables, columns, or partitions with low-cardinality strings, the cumulative size of these dictionaries can exhaust the FE's JVM heap.
2. Immediate Troubleshooting Steps
Step 1: Identify the Memory Consumer
Use the internal memory tracker to see which module is consuming the most heap.
sql
-- Available in StarRocks v3.3 and later
SHOW PROC '/memory_usage';
Look for modules named "Dictionary", "GlobalDict", or "Metadata". If "Dictionary" is high, the global dictionary cache is the primary culprit.
Step 2: Check for Thread Pool Rejections
Search your fe.log or fe.warn.log for the following pattern:
Task ... rejected from cache-dict ... pool size = 16
If this is frequent, your query concurrency or the sheer number of dictionaries being loaded is overwhelming the FE.
Step 3: Mitigate via Configuration
If the FE is at risk of crashing (OOM), you can temporarily disable the low-cardinality optimization. This will stop the FE from loading new dictionaries into memory.
sql
-- Disable globally (requires restart or applies to new sessions)
SET GLOBAL cbo_enable_low_cardinality_optimize = false;
Note: This might slightly increase query latency for string-heavy queries, but it will stabilize the FE memory.
3. Root Cause Analysis & Solutions
Potential Cause | Solution
Too many optimized columns | Check your tables for columns with cardinality just under the threshold (default 255). If you have hundreds of such columns across many partitions, the FE memory will bloat.
High Partition Count | Queries scanning thousands of partitions, each requiring a dictionary load, can saturate the thread pool. Consider reducing partition granularity or using TRUNCATE instead of many small deletes/loads.
Insufficient FE Heap | If your metadata and dictionaries simply outgrow the default heap, increase the -Xmx value in fe.conf. For large clusters, 16GB–32GB is common.
Stale Dictionaries | In some versions, dictionaries might not be evicted fast enough. Upgrading to the latest maintenance release (v3.2.x or v3.3.x) often includes fixes for dictionary cache lifecycle management.
4. Advanced Tuning
If you must keep the optimization enabled but need to reduce the "frenzy" of the cache-dict pool:
* Lower the Threshold: You can reduce the low_cardinality_threshold (default 255) so fewer columns qualify for the optimization.
sql
-- In fe.conf (requires restart)
low_cardinality_threshold = 128
* Analyze Statistics: Ensure your statistics are up to date. The optimizer uses cardinality stats to decide whether to trigger a dictionary load. If stats are missing or stale, it might make suboptimal caching decisions.
Recommended Next Step: Run jmap -histo <FE_PID> | head -n 20 to see if com.starrocks.sql.optimizer.statistics.CacheDict or similar objects are dominating the heap. If you see high counts of these objects, the Global Dictionary cache is definitely the bottlenecked.
ReferencesRocky
05/05/2026, 12:26 AMRocky
05/05/2026, 12:37 AMPUBLISH_VERSION contexts), which causes thread pool saturation and eventual system unresponsiveness.
1. Root Cause: Global Dictionary Bloat
The CacheDictManager is responsible for caching string-to-integer mappings for low-cardinality columns to speed up queries. Having 30+ optimized columns per table is very high. With high transaction throughput, the FE is likely loading and maintaining a massive number of distinct dictionary versions across many partitions.
2. Immediate Mitigation (Stabilization)
To prevent the FE from crashing or becoming completely unresponsive, you should disable the Low Cardinality Optimization globally. This will stop the FE from attempting to load new dictionaries into the heap, allowing the G1GC to reclaim space as old dictionaries expire.
sql
-- Apply globally to stop the FE from loading new dictionaries
SET GLOBAL cbo_enable_low_cardinality_optimize = false;
Note: This will not break queries; it simply reverts the optimizer to using standard string processing instead of the dictionary-encoded integer path.
3. Tuning the Dictionary Thresholds
If you want to re-enable the feature later, you must reduce the number of columns that qualify for it.
* Version 3.5.0+: Adjust the threshold in `fe.conf`:
properties
# Reduce from default 255 to something smaller like 64 or 128
low_cardinality_threshold = 64
* Earlier Versions: You may need to manually identify and disable the optimization for specific columns by altering the table or using session variables to control the rewrite.
4. Handling the cache-dict Thread Pool Saturation
The saturation (184k rejections) is largely a side-effect of the JVM being "stunned" by high GC overhead. However, if your workload genuinely requires high-concurrency dictionary loading, check if your version supports the internal config cache_dict_thread_pool_size (this is often internal/hidden).
* Run ADMIN SHOW FRONTEND CONFIG LIKE "%dict%"; to see if your version allows manual expansion of this pool.
5. Memory Recovery & Monitoring
* Increase Heap: For a high-throughput cluster with heavy metadata and dictionary usage, 32GB is often the "danger zone." If your hardware permits, consider increasing -Xmx to 64GB.
* Detailed Memory Breakdown: If you are on v3.3+, use the internal tracker to confirm the dictionary size:
sql
SHOW PROC '/memory_usage';
Look for the "Dictionary" or "CacheDictManager" modules. If they exceed 10-15GB, you have a clear over-caching problem.
* Manual Cleanup: Currently, there is no SQL command to "flush" the internal Global Dictionary cache specifically. Disabling the feature (cbo_enable_low_cardinality_optimize = false) and waiting for LRU eviction or a rolling FE restart is the standard procedure.
6. Cascading Issues (PUBLISH_VERSION and Thrift)
* Orphaned Tasks: The cannot find task. type: PUBLISH_VERSION errors occur because the FE's internal task map is likely being cleared or the FE is so slow that the BE's report-back exceeds the FE's internal timeout/retention.
* Thrift Threads: The 16,000+ thread count is extremely high (the default max is usually 4,096). This indicates that RPC requests are "piling up" because the FE is stuck in GC pauses and cannot complete the work, forcing the Thrift server to spawn more threads to handle new incoming connections until it hits OS limits.
Recommendation:
1. Disable cbo_enable_low_cardinality_optimize.
2. Perform a rolling restart of FEs to clear the "ghost" Thrift threads and reset the heap.Rocky
05/05/2026, 12:37 AM