| name | tablet |
| description | Use when investigating tablet-level structural problems: data skew (one tablet 10× larger than peers), too many tablet versions blocking writes (too many versions error), error-state replicas, over-sharding causing high FE metadata overhead, or disk balance retry loops. Covers SHOW TABLET analysis, be_tablets SQL queries, bucket key optimization, and tablet health thresholds (VersionCount, DataSize variance, num_rowset). |
| version | 2.0.0 |
| category | tablet |
| keywords | ["tablet health","tablet balance","data skew","bucket","compaction","version count"] |
| tools | [] |
| related_cases | ["case-004-disk-balancing","case-014-scan-skew"] |
Tablet Governance
Investigation guide for tablet health, balance, data skew, bucket optimization, and
version-count / compaction-lag issues.
Five root causes account for the vast majority of cases:
- Cause A — data skew from low-cardinality bucket key
- Cause B — too many versions (compaction lag)
- Cause C — error state replicas (VERSION_ERROR, SCHEMA_ERROR)
- Cause D — too many tablets (over-sharding from fine partitions or excess buckets)
- Cause E — disk balance retry loop (metadata state inconsistency)
Metric Taxonomy — Read This First
Before using any metrics, understand the two-layer observability structure:
SQL-based observability
SHOW TABLET FROM <table> — per-tablet summary for a table:
| Field | Meaning |
|---|
TabletId | Tablet identifier |
ReplicaId | Replica identifier on a specific BE |
BackendId | BE hosting this replica |
SchemaHash | Schema version hash (mismatch indicates SCHEMA_ERROR) |
Version | Latest visible version |
VersionCount | Number of versions (rowsets) tracked by the system |
LstFailedVersion | Last version that failed to load — non-zero indicates replica problem |
LstSuccessVersion | Last version successfully applied |
DataSize | Storage size of this replica in bytes |
RowCount | Row count estimate |
State | Replica state: NORMAL, CLONE, SCHEMA_CHANGE, ALTER |
SHOW TABLET <tablet_id> — single tablet detail:
| Field | Meaning |
|---|
DbName / TableName / PartitionName | Context for this tablet |
State | Tablet state |
VersionCount | Version count across replicas (from detailcmd) |
CompactionStatus URL | Link to BE compaction state JSON — shows last_base_compaction_time, cumulative_layer_point |
information_schema.be_tablets — per-replica metrics from BE (most detailed):
| Field | Meaning |
|---|
be_id | BE hosting this replica |
tablet_id | Tablet identifier |
num_version | Total version count (all edits ever) |
num_rowset | Active rowsets in current version — key compaction health indicator |
num_segment | Segment files (num_rowset × segments per rowset) |
data_size | Raw data size in bytes |
num_row | Row count |
state | Replica state |
medium_type | HDD or SSD |
How to retrieve metrics
Option 1 — SQL (primary method)
SHOW TABLET FROM <table_name>;
SHOW TABLET <tablet_id>;
SHOW PROC '/dbs/<db_id>/<table_id>/<partition_id>';
ADMIN SHOW REPLICA DISTRIBUTION FROM <table_name>;
SELECT be_id, tablet_id, num_rowset, num_version, num_segment,
ROUND(data_size / 1024 / 1024, 1) AS data_size_mb,
num_row, state
FROM information_schema.be_tablets
WHERE table_id = <table_id>
ORDER BY num_rowset DESC LIMIT 20;
SHOW PROC "/statistic";
SHOW PROC "/statistic/<db_id>";
SELECT be_id, tablet_id, num_rowset, num_segment,
ROUND(data_size / 1024 / 1024, 1) AS data_size_mb
FROM information_schema.be_tablets
WHERE num_rowset > 100
ORDER BY num_rowset DESC LIMIT 20;
SELECT be_id, tablet_id,
ROUND(data_size / 1024 / 1024, 1) AS data_size_mb,
num_row
FROM information_schema.be_tablets
WHERE table_id = <table_id>
ORDER BY data_size DESC LIMIT 20;
SELECT be_id, COUNT(*) AS tablet_count,
SUM(data_size) / 1024 / 1024 / 1024 AS total_gb
FROM information_schema.be_tablets
GROUP BY be_id
ORDER BY tablet_count DESC;
Option 2 — curl BE HTTP port (compaction and rowset state)
curl "http://<be_ip>:8040/api/compaction/show?tablet_id=<tablet_id>"
curl -s "http://<be_ip>:8040/metrics" | grep -E "compaction_score|num_rowset"
Option 3 — BE HTTP tablet detail
curl "http://<be_ip>:8040/api/meta/header?tablet_id=<tablet_id>"
Default HTTP ports: BE = 8040, FE = 8030.
Key rules for interpretation:
VersionCount > 500 continuously (from SHOW TABLET) indicates compaction cannot keep up with write rate — this is a compaction problem (see skill 12-compaction), not a tablet governance problem.
DataSize variance > 10x across tablets of the same table strongly indicates data skew from a low-cardinality or hot-value bucket key.
num_rowset in be_tablets equals VersionCount for non-PK tables; both come from _rs_metas.size(). For PK tables, num_rowset = active rowsets in latest version (usually smaller).
LstFailedVersion > 0 and LstFailedVersion != LstSuccessVersion on a replica means that replica has a version gap — it needs repair clone.
- Total tablet count per cluster should be monitored: > 500,000 tablets creates FE metadata overhead and BE file descriptor pressure.
Tablet Health Reference
| Metric | Healthy | Warning | Act Immediately |
|---|
VersionCount (SHOW TABLET) | < 50 | 50–500 | > 500 sustained (compaction lag) |
DataSize variance across tablets (same table) | < 2x | 2–10x | > 10x (data skew) |
num_rowset (be_tablets) | < 20 | 20–100 | > 100 (rowset pile-up) |
num_row std deviation across tablets | small | std_dev > 10% of mean | single tablet holds > 50% of total rows |
| Tablet count per BE | balanced | 20% variance | > 2x between BEs (scan skew) |
| Total tablet count in cluster | < 100,000 | 100,000–500,000 | > 500,000 (FE heap and FD pressure) |
LstFailedVersion on replica | 0 or equals LstSuccessVersion | Any non-zero gap | Gap growing and CloningTabletNum not rising |
Phase 1 — Assess Tablet Health
Step 1.1 — Cluster-wide quick scan
SHOW PROC "/statistic";
UnhealthyTabletNum = 0 everywhere → proceed to performance-focused steps
UnhealthyTabletNum > 0 → note which DB IDs are affected, go to Step 1.2
Step 1.2 — BE-level tablet scan
SELECT be_id, COUNT(*) AS tablet_count,
MAX(num_rowset) AS max_rowsets,
SUM(CASE WHEN num_rowset > 100 THEN 1 ELSE 0 END) AS tablets_over_100_rowsets,
SUM(CASE WHEN num_rowset > 500 THEN 1 ELSE 0 END) AS tablets_over_500_rowsets
FROM information_schema.be_tablets
GROUP BY be_id
ORDER BY max_rowsets DESC;
SELECT table_id, be_id,
MAX(data_size) / 1024 / 1024 AS max_tablet_mb,
MIN(data_size) / 1024 / 1024 AS min_tablet_mb,
MAX(data_size) / NULLIF(MIN(data_size), 0) AS size_ratio
FROM information_schema.be_tablets
GROUP BY table_id, be_id
HAVING size_ratio > 10
ORDER BY size_ratio DESC LIMIT 10;
Step 1.3 — Identify issue type
| Signal from Step 1.2 | Points toward |
|---|
max_rowsets > 100 on multiple BEs | Cause B — compaction lag |
size_ratio > 10 in data skew query | Cause A — bucket key skew |
UnhealthyTabletNum > 0, ErrorStateTabletNum > 0 | Cause C — error state replicas |
| Total tablet count > 500,000 | Cause D — over-sharding |
history_tablets shows balance tasks cycling | Cause E — disk balance retry loop |
Phase 2 — Identify Problem Tablets
Step 2.1 — Drill into suspect table
SHOW TABLET FROM <table_name>;
ADMIN SHOW REPLICA DISTRIBUTION FROM <table_name>;
SELECT be_id, tablet_id, num_rowset, num_version,
ROUND(data_size / 1024 / 1024, 1) AS data_size_mb,
num_row, state
FROM information_schema.be_tablets
WHERE table_id = <table_id>
ORDER BY data_size DESC LIMIT 30;
Step 2.2 — Confirm root cause
Cause A — Data skew
Confirm all match:
DataSize varies > 10x between tablets of the same table
num_row also varies proportionally (not a compaction artifact)
- Distribution key has low cardinality or a dominant hot value
→ Go to Phase 3, Cause A
Cause B — Too many versions
Confirm all match:
num_rowset > 100 in be_tablets for multiple tablets
VersionCount > 500 from SHOW TABLET <tablet_id>
- Compaction score rising (check skill 12-compaction for compaction-specific diagnosis)
→ Go to Phase 3, Cause B
Cause C — Error state replicas
Confirm all match:
ErrorStateTabletNum > 0 in SHOW PROC "/statistic"
SHOW TABLET FROM <table> shows LstFailedVersion > 0 and differs from LstSuccessVersion
- Replica
State is not NORMAL
→ Go to Phase 3, Cause C
Cause D — Too many tablets
Confirm all match:
- Total tablet count > 500,000 or tablet count per BE > 50,000
- Many small partitions (< 100MB each) or excess bucket count relative to data size
- BE log shows FD warnings or
ulimit -n approaching limit
→ Go to Phase 3, Cause D
Cause E — Disk balance retry loop
Confirm all match:
SHOW PROC "/cluster_balance/history_tablets" shows same tablet repeatedly failing
ErrMsg references metadata state or _shutdown_tablets
- BE IO elevated on specific disk without progress
→ Go to Phase 3, Cause E
Phase 3 — Take Action by Cause
Cause A — Data skew (low-cardinality bucket key)
Step A-1: Confirm skew pattern
SELECT <bucket_key_col>, COUNT(*) AS cnt
FROM <table_name>
GROUP BY <bucket_key_col>
ORDER BY cnt DESC LIMIT 20;
Step A-2: Identify correct bucket key
The bucket key must have high cardinality and uniform distribution. Good candidates:
- User ID, order ID, device ID (UUID-like)
- Composite keys that spread data evenly
Avoid: status, region, date, boolean columns.
Step A-3: Recreate table with better bucket key
CREATE TABLE <table_name>_new
DISTRIBUTED BY HASH(<high_cardinality_col>) BUCKETS <n>
AS SELECT * FROM <table_name>;
ALTER TABLE <table_name> RENAME <table_name>_old;
ALTER TABLE <table_name>_new RENAME <table_name>;
Step A-4: Use StarRocksBuckets CLI for analysis
The standalone StarRocksBuckets utility can analyze existing distributions and generate
ALTER TABLE DDL for optimal bucket count and key. Run against the affected table before
deciding on the new schema.
Cause B — Too many versions (compaction lag)
Step B-1: Identify affected tablets
SELECT be_id, tablet_id, num_rowset,
ROUND(data_size / 1024 / 1024, 1) AS data_size_mb
FROM information_schema.be_tablets
WHERE num_rowset > 100
ORDER BY num_rowset DESC LIMIT 20;
Step B-2: Confirm compaction type and take action
This is a compaction problem. Use skill 12-compaction for the full diagnosis.
Quick remediation:
curl -XPOST "http://<be_ip>:8040/api/compact?compaction_type=cumulative&tablet_id=<tablet_id>"
curl -XPOST "http://<be_ip>:8040/api/compact?compaction_type=base&tablet_id=<tablet_id>"
UPDATE information_schema.be_configs SET value = 8
WHERE name = 'max_compaction_concurrency';
UPDATE information_schema.be_configs SET value = 2
WHERE name = 'cumulative_compaction_check_interval_seconds';
Step B-3: Reduce import frequency if needed
ALTER ROUTINE LOAD FOR <job_name>
PROPERTIES (
"max_batch_interval" = "60",
"desired_concurrent_number" = "3"
);
Cause C — Error state replicas
Step C-1: Find affected replicas
SHOW TABLET <tablet_id>;
Step C-2: Trigger repair clone
ADMIN SET REPLICA STATUS PROPERTIES(
"tablet_id" = "<tablet_id>",
"backend_id" = "<bad_be_id>",
"status" = "bad"
);
Step C-3: Force priority repair
ADMIN REPAIR TABLE <table_name>;
ADMIN REPAIR TABLE <table_name> PARTITION (<partition_name>);
Step C-4: Verify
SHOW TABLET <tablet_id>;
Cause D — Too many tablets (over-sharding)
Step D-1: Quantify the problem
SELECT COUNT(*) AS total_tablets FROM information_schema.be_tablets;
SELECT be_id, COUNT(*) AS tablet_count
FROM information_schema.be_tablets
GROUP BY be_id ORDER BY tablet_count DESC;
SELECT table_id, COUNT(DISTINCT tablet_id) AS tablet_count
FROM information_schema.be_tablets
GROUP BY table_id
ORDER BY tablet_count DESC LIMIT 20;
Step D-2: Check file descriptor pressure
ps aux | grep starrocks_be
ls /proc/<be_pid>/fd | wc -l
cat /proc/<be_pid>/limits | grep "open files"
Step D-3: Increase FD limit (immediate relief)
ulimit -n 1000000
* soft nofile 1000000
* hard nofile 1000000
Step D-4: Reduce tablet count structurally
ALTER TABLE <table_name>
SET ("dynamic_partition.time_unit" = "MONTH");
CREATE TABLE <table_name>_new
DISTRIBUTED BY HASH(<col>) BUCKETS <lower_n>
AS SELECT * FROM <table_name>;
DROP TABLE <old_table_name>;
ALTER TABLE <table_name>
SET ("dynamic_partition.history_partition_num" = "90");
Cause E — Disk balance retry loop
Step E-1: Confirm the loop
SHOW PROC "/cluster_balance/history_tablets";
Step E-2: Restart all BE nodes (resets _shutdown_tablets state)
./bin/stop_be.sh && sleep 5 && ./bin/start_be.sh
After restart, _shutdown_tablets state is cleared and the balance task can proceed cleanly.
Step E-3: Monitor recovery
SHOW PROC "/cluster_balance/history_tablets";
SHOW PROC "/statistic";
Phase 4 — Verify Recovery
SHOW PROC "/statistic";
ADMIN SHOW REPLICA DISTRIBUTION FROM <table_name>;
SELECT be_id, MAX(num_rowset) AS max_rowsets,
SUM(CASE WHEN num_rowset > 100 THEN 1 ELSE 0 END) AS tablets_over_100
FROM information_schema.be_tablets
WHERE table_id = <table_id>
GROUP BY be_id;
SHOW TABLET <tablet_id>;
SELECT COUNT(*) AS total_tablets FROM information_schema.be_tablets;
Tablet Governance Config Parameters
| Parameter | Default | Description | Dynamic |
|---|
tablet_max_versions | 1000 | Max versions before write block ("too many versions") | Yes (v2.3+) |
cumulative_compaction_num_threads_per_disk | 1 | Cumulative compaction threads per disk | No (restart) |
base_compaction_num_threads_per_disk | 1 | Base compaction threads per disk | No (restart) |
max_compaction_concurrency | -1 (unlimited) | Global compaction thread cap | Yes (v2.5+) |
cumulative_compaction_check_interval_seconds | 1 | Cumulative compaction scheduler poll interval | Yes (v2.5+) |
base_compaction_check_interval_seconds | 60 | Base compaction scheduler poll interval | Yes (v2.5+) |
base_cumulative_delta_ratio | 0.3 | Cumulative/base size ratio to trigger base compaction | Yes (v2.5+) |
base_compaction_interval_seconds_since_last_operation | 86400 | Periodic base compaction timer | Yes (v2.5+) |
parallel_clone_task_per_path | 8 | Clone threads per disk path (for balance repair) | No (restart) |
storage_page_cache_limit | system-dependent | Block cache size; affects tablet read performance | No (restart) |
max_tablet_num_per_shard | 1024 | Max tablets per shard dir; tune for high tablet count | No (restart) |
Session-level (affects queries on tables, not stored in be.conf):
| Session Variable | Default | Description |
|---|
enable_profile | false | Enable query profiling (to inspect scan skew) |
pipeline_dop | 0 (auto) | Query parallelism; affects per-tablet scan concurrency |
Common Issues
| Issue | Cause | Fix |
|---|
too many tablet versions | Compaction can't keep up with ingest | Tune compaction; reduce import frequency (see skill 12-compaction) |
| Single tablet 100x larger than others | Bad bucket key (low cardinality / hot value) | Re-bucket with high-cardinality key (Cause A) |
| Disk balance retries forever | _shutdown_tablets state inconsistent | Restart all BEs (Cause E) |
VERSION_ERROR on a replica | Replica desync after network blip | Mark replica bad to trigger clone (Cause C) |
| Tablet count too high | Too-fine partition or excess buckets | Coarser partition; reduce bucket count (Cause D) |
| Queries slow on specific table | Scan skew from tablet size imbalance | Check DataSize distribution; fix bucket key |
Related Cases
case-004-disk-balancing — IO saturation from migration retry loop
case-014-scan-skew — data skew driven by bucket key with hot value
Causal Chains
Chain 1: Low-Cardinality Bucket Key → Data Skew → Single Tablet Straggler
Table created with low-cardinality distribution key
↓ observable: SHOW TABLET FROM <table> shows DataSize variance > 10x across tablets
All data for dominant key values routes to one or few tablets
↓ observable: information_schema.partitions shows uneven DATA_LENGTH; SHOW PROC '/cluster_balance/tablet_checker' may show oversized tablets
Query scan assigns one instance to the large tablet; parallelism nominally full
↓ observable: Profile per-instance Active time in OLAP_SCAN_NODE shows one instance orders of magnitude slower
Query bottlenecked on single slow scan instance; others idle-wait
↓ observable: max instance active time >> avg; total query time equals slowest instance
Slow queries despite sufficient cluster resources and parallelism.
Trigger conditions: Distribution key chosen by convenience (status, region) not cardinality; business-domain skewed data.
Break point: Recreate table with high-cardinality distribution key or composite bucket key; increase bucket count.
Chain 2: Inverted Index Pending Tasks → Version Count Rises → Compaction Lag → Scan Slow
Inverted index build tasks accumulate due to high write rate or slow index worker
↓ observable: BE log inverted index pending task queue depth increasing; index build lag metric rising
Tablet cannot compact rowsets with pending index tasks; version count rises
↓ observable: SELECT num_rowset FROM information_schema.be_tablets shows affected tablets with high counts; BE log compaction skipped due to pending index
Compaction falls behind; many unmerged rowsets accumulate
↓ observable: Grafana compaction score rising; BE log compaction score warnings
Scan must MERGE many rowsets at query time
↓ observable: Profile MERGE time dominant in OLAP_SCAN_NODE; inverted index scan time elevated
Slow queries on tables with inverted indexes under high write load.
Trigger conditions: Inverted index on high-cardinality columns with frequent updates; index worker thread count insufficient.
Break point: Increase inverted index build thread count; temporarily reduce import frequency.
Chain 3: Tablet Count Too High Per BE → FD Limit Hit → Write Fails
Table/partition proliferation results in too many tablets per BE
↓ observable: SHOW PROC '/cluster_balance/tablet_checker' shows high tablet count per BE; BE log tablet count warning
Each tablet holds open file descriptors for segment, bloom filter, and index files
↓ observable: ls /proc/<be_pid>/fd | wc -l approaches ulimit -n value
BE reaches OS fd limit; cannot open new segment files for writes or reads
↓ observable: BE log "Too many open files"; ulimit -n shows limit lower than actual FD usage
New segment writes fail; load jobs return IO error from affected BE
↓ observable: Load job error: file open failed; TabletCount in Profile very high
Write failures on BEs with extreme tablet counts.
Trigger conditions: Many small partitions without TTL; high bucket count tables; FD limit not tuned beyond OS default (65535).
Break point: Increase ulimit -n for BE process (typically to 1000000); implement partition TTL; reduce bucket count on over-sharded tables.
Resources