Ben Kimpel
05/03/2026, 11:47 PMRocky
05/03/2026, 11:48 PMmysql_service_nio_enable_keep_alive is set to true in StarRocks (which it is by default), the Linux OS default for sending keepalive packets is typically 2 hours (tcp_keepalive_time). If your network timeout is 5 minutes, the OS won't send a keepalive packet in time to "prove" the connection is still active.
* The Fix: Configure the FE operating system to send TCP keepalive packets more frequently. On your FE nodes, adjust the following sysctl parameters:
bash
# Set to a value lower than your Load Balancer timeout (e.g., 60 seconds)
sysctl -w net.ipv4.tcp_keepalive_time=60
sysctl -w net.ipv4.tcp_keepalive_intvl=10
sysctl -w net.ipv4.tcp_keepalive_probes=6
3. StarRocks Session Timeouts
Check if your session variables are cutting the connection short. You can check these by running SHOW VARIABLES LIKE '%timeout%';.
* query_timeout: Ensure this is set high enough. The default is often 300 seconds (5 minutes). For a 15-minute query, you must increase this:
sql
SET GLOBAL query_timeout = 3600; -- 1 hour
* wait_timeout / interactive_timeout: These control how long an idle connection stays open. The default is 8 hours, so these are rarely the issue unless they were manually lowered.
* net_read_timeout / net_write_timeout: These control the timeout for reading/writing data from/to the network. Ensure these are not set to low values.
4. FE Configuration: mysql_service_kill_after_disconnect
If the query continues to run on the server even after the client is stuck, it might be because this FE setting is disabled.
* mysql_service_kill_after_disconnect: (Default true). If this is false, StarRocks won't kill the query when the client disconnects. While keeping it false allows the query to "finish" in the background, it often leads to the exact "stuck client" state you are seeing because the client's socket is orphaned.
Summary Checklist
1. Is there a Load Balancer? Increase its Idle Timeout.
2. Linux Kernel: Lower tcp_keepalive_time on FE nodes.
3. SQL Session: Run SET query_timeout = 1800; before your query to ensure the engine doesn't stop the query early.
References
• administration/management/FE_configuration.mdBen Kimpel
05/03/2026, 11:54 PMBen Kimpel
05/03/2026, 11:54 PMRocky
05/03/2026, 11:54 PMnet_read_timeout and net_write_timeout are included only for MySQL client compatibility and have no practical usage or effect on how StarRocks handles queries.
Changing these variables will not help with your 15-minute query issue.
What actually controls timeouts?
If your query is running for 15 minutes, you should focus on these three things instead:
1. query_timeout (The Server-Side Limit):
The default is 300 seconds (5 minutes). If your query is running for 15 minutes and actually finishing, you (or someone else) must have already increased this. If you haven't, the query would typically be killed by the FE after 5 minutes with a Query exceeded time limit error.
sql
SET query_timeout = 1800; -- Set to 30 minutes
2. wait_timeout (The Connection Idle Limit):
This determines how long the server waits for a new request on an idle connection. The default is 8 hours, so this is rarely the cause of a query getting "stuck" mid-execution.
3. Network/TCP Keepalives (The "Stuck Client" Culprit):
Since you mentioned the query "completes successfully but the client doesn't know it," the problem is almost certainly a network partition.
* While the query is running for 15 minutes, if no data is being sent back to the client, your firewall or Load Balancer likely sees the connection as "idle" and drops it.
* Because net_read_timeout doesn't do anything in StarRocks, the client just sits there waiting on a socket that the network infrastructure has already closed.
Recommendation
To stop the client from getting stuck:
* Don't bother with net_read_timeout.
* Check your Load Balancer/Proxy idle timeout: Ensure it is set to at least 900–1000 seconds.
* Lower Linux TCP Keepalives: On the FE host, set net.ipv4.tcp_keepalive_time to something short (like 60 seconds) so the OS sends "heartbeat" packets to keep the network path open while the query is processing.
References
• sql-reference/System_variable.md
• administration/management/FE_configuration.md
• administration/management/BE_configuration.mdBen Kimpel
05/03/2026, 11:59 PMRocky
05/04/2026, 12:00 AMSUBMIT TASK or CREATE TASK statements.
SQL identifiers (like task names, table names, or database names) must be literal strings or unquoted names. The StarRocks engine does not currently support string interpolation or variables in the identifier position of these commands.
Why this doesn't work in SQL
The following syntax will result in a parsing error:
sql
SET @my_var = 'daily_sync';
-- This will NOT work
SUBMIT TASK @my_var AS INSERT INTO ...;
How to achieve dynamic naming
To use dynamic names, you generally have two options:
1. Use an External Orchestrator (Recommended)
Since SUBMIT TASK is often used for ETL, most users handle dynamic naming in their application logic or orchestration tool (like Python, Airflow, or a Shell script).
* Python Example:
python
task_name = f"sync_{datetime.now().strftime('%Y%m%d')}"
query = f"SUBMIT TASK {task_name} AS INSERT INTO ..."
cursor.execute(query)
2. Let StarRocks Generate the Name
If you do not provide a task name, StarRocks will automatically generate a unique one for you. You can then retrieve this name from the result of the SUBMIT TASK command or by querying the metadata:
sql
-- Submit without a name
SUBMIT TASK AS INSERT INTO ...;
-- Check what name was assigned
SELECT task_name, create_time
FROM information_schema.tasks
ORDER BY create_time DESC LIMIT 1;
Note on Session Variables
While you cannot use session variables for the task name, you can use them to configure the task's execution environment via the PROPERTIES clause:
sql
SUBMIT TASK my_task
PROPERTIES (
"session.query_timeout" = "3600",
"session.enable_profile" = "true"
)
AS INSERT INTO ...;
Summary: You must construct the SQL string with the desired name in your client application before sending it to StarRocks. Dynamic identifier resolution is not supported natively in StarRocks SQL.
References
• sql-reference/sql-statements/prepared_statement.md
• sql-reference/user_defined_variables.md
• sql-reference/sql-functions/Python_UDF.mdBen Kimpel
05/04/2026, 12:24 PMRocky
05/04/2026, 12:24 PMALTER TABLE ... SWAP WITH on a base table that a materialized view (MV) depends on, the following things happen:
1. The Materialized View Becomes Inactive
StarRocks automatically sets any dependent materialized views to an Inactive state. This is a safety mechanism to prevent data inconsistency, as the underlying metadata, schema, or data distribution of the "new" swapped table might no longer align with what was used to build the MV.
2. Query Acceleration Stops
Once the MV is inactive:
* It can no longer be used for transparent query rewrite (query acceleration).
* If it is an asynchronous MV, it will stop its refresh schedule until it is reactivated.
3. Constraints are Removed
Any Unique Key or Foreign Key constraints that were defined on the MV based on the original table will be removed and will no longer be available.
──────────
How to Fix It
After the swap is complete, you must manually reactivate the materialized view to make it usable again.
1. Check the status:
You can verify the status of your MV by running:
sql
SHOW MATERIALIZED VIEWS LIKE 'your_mv_name';
-- Look at the 'IsActive' column
2. Reactivate the MV:
sql
ALTER MATERIALIZED VIEW your_mv_name ACTIVE;
3. Refresh the data:
Since the base table was swapped, the data in the MV is likely stale. You should trigger a refresh:
sql
REFRESH MATERIALIZED VIEW your_mv_name;
Important Note on Synchronous (Rollup) MVs
If you are using the older "Synchronous Materialized Views" (essentially Rollups created with CREATE MATERIALIZED VIEW without the REFRESH keyword), swapping the base table is generally more restrictive. If the schema of the two swapped tables does not match the Rollup definition exactly, the swap may fail or the Rollup may be dropped. It is highly recommended to use Asynchronous MVs for better flexibility in these scenarios.
References
• sql-reference/sql-statements/table_bucket_part_index/ALTER_TABLE.md
• sql-reference/sql-statements/materialized_view/ALTER_MATERIALIZED_VIEW.md
• knowledge/usage/best-practice.md
• using_starrocks/async_mv/Materialized_view.mdBen Kimpel
05/04/2026, 3:21 PMRocky
05/04/2026, 3:22 PMSUBMIT TASK will significantly impact performance, primarily on the Frontend (FE) side.
SUBMIT TASK is designed for long-running, asynchronous ETL jobs, not for high-frequency, low-latency micro-tasks. Here is why doing this will cause issues:
1. Bottlenecked by Default Limits
StarRocks has conservative default limits for the task engine. If you submit thousands of tasks at once, you will immediately hit these walls:
* task_runs_concurrency (Default: 4): Only 4 tasks will actually run in parallel. The other 996+ will sit in a "PENDING" state.
* task_runs_queue_length (Default: 500): If your pending queue exceeds 500, new SUBMIT TASK requests will be suspended or rejected.
* task_runs_max_history_number (Default: 10,000): StarRocks keeps a history of task runs. High-frequency tasks will quickly fill this history, triggering frequent background cleanup processes.
2. FE Metadata Pressure
Every task you submit is stored in the FE's memory and persisted in the BDBJE (the internal metadata store).
* Memory Bloat: Storing thousands of task definitions and their run histories (information_schema.task_runs) consumes FE heap memory.
* GC Pauses: A high volume of small tasks creates a lot of metadata "churn." As tasks finish and are cleaned up, the Java Virtual Machine (JVM) on the FE will have to perform more frequent Garbage Collection (GC), which can lead to cluster-wide "stop-the-world" pauses.
* Leader FE Overload: Only the Leader FE manages the task scheduler. Flooding it with thousands of tasks can make the Leader FE unresponsive to other critical operations like schema changes or connection handling.
3. Scheduling Overhead
The FE background daemon (controlled by task_check_interval_second) must periodically scan the task list to decide what to run next. The overhead of managing the state machine (PENDING → RUNNING → SUCCESS/FAILED) for a task that only takes 1 second to execute is often higher than the execution time of the task itself.
──────────
What should you do instead?
If you find yourself needing to run thousands of small operations, SUBMIT TASK is the wrong tool. Consider these alternatives:
1. Batching: Instead of 1,000 tasks each doing one INSERT, create one task that performs a single large INSERT INTO ... SELECT ... or a batch of inserts.
2. Routine Load: If these small tasks are for data ingestion from Kafka, use Routine Load. It is purpose-built for high-frequency, small-batch loading and is much more efficient than the Task engine.
3. Stream Load: For high-frequency writes from an external application, use Stream Load. It bypasses the SQL parsing and task scheduling overhead entirely.
4. External Orchestrator: If you need complex logic, use an external tool like Apache Airflow or a simple Python script to manage the concurrency and only send the SQL to StarRocks when the cluster has capacity.
Summary: Only use SUBMIT TASK for heavy ETL jobs (e.g., refreshing a Materialized View or doing a massive historical data migration) that you want to run in the background. For everything else, use standard synchronous SQL or dedicated loading tools.
References
• sql-reference/sql-statements/loading_unloading/ETL/SUBMIT_TASK.md
• administration/management/resource_management/query_queues.mdBen Kimpel
05/04/2026, 3:24 PMRocky
05/04/2026, 3:24 PMSUBMIT TASK, you have a few options depending on whether you want to stop a single run or delete the task definitions entirely.
1. The Quickest Way: DROP TASK
If you want to stop a task and prevent it from running again (or clean up the thousands of tasks you just created), use DROP TASK. This command stops the currently running execution (the "TaskRun") and deletes the task metadata.
sql
DROP TASK `your_task_name`;
Note: If you created thousands of tasks, you will likely need to generate a script to drop them in bulk, as there is no DROP ALL TASKS command.
2. Stop Without Deleting: ALTER TASK ... SUSPEND
(Supported in StarRocks v4.1+)
If you want to stop a running task but keep the task definition (for example, if it's a scheduled task), you can suspend it. This kills any active runs and pauses the scheduler.
sql
ALTER TASK `your_task_name` SUSPEND;
3. Killing the Underlying Query
Sometimes a task is "submitted," but the underlying SQL query is already running on the Be (Backend). To kill the actual execution thread:
1. Find the `QueryId`:
sql
SELECT query_id, state, info FROM information_schema.task_runs WHERE state = 'RUNNING';
2. Kill the query:
sql
KILL QUERY <query_id>;
──────────
How to handle "thousands" of tasks
Since you mentioned you created thousands of tasks, manual deletion is difficult. You can generate the cleanup SQL using the `information_schema`:
Step 1: Generate the DROP statements
sql
SELECT CONCAT('DROP TASK `', task_name, '`;')
FROM information_schema.tasks
WHERE database_name = 'your_db_name';
Step 2: Copy the results and execute them as a batch script.
Useful Monitoring Views
If you need to see which tasks are clogging up the queue, use these views:
* To see the task templates: SELECT * FROM information_schema.tasks;
* To see the execution status (Pending/Running): SELECT * FROM information_schema.task_runs ORDER BY create_time DESC;
References
• sql-reference/sql-statements/loading_unloading/ETL/DROP_TASK.md
• sql-reference/sql-statements/loading_unloading/ETL/ALTER_TASK.md
• sql-reference/sql-statements/loading_unloading/ETL/SUBMIT_TASK.md
_TASK)
References
• sql-reference/sql-statements/loading_unloading/ETL/DROP_TASK.md
• using_starrocks/Cost_based_optimizer.md
• administration/management/compaction.md
• sql-reference/sql-statements/cbo_stats/KILL_ANALYZE.md
• sql-reference/sql-statements/loading_unloading/ETL/ALTER_TASK.md
• sql-reference/sql-statements/table_bucket_part_index/CANCEL_ALTER_TABLE.mdBen Kimpel
05/04/2026, 4:07 PMRocky
05/04/2026, 4:08 PMDESC
The DESCRIBE (or DESC) command is the standard way to quickly see the column names, types, and nullability.
sql
DESC your_table_name;
* Best for: A quick look at the schema in a readable format.
* Output: Field, Type, Null, Key, Default, Extra.
2. Using SHOW COLUMNS
This is a MySQL-compatible command that provides similar information to DESC.
sql
SHOW COLUMNS FROM your_table_name;
3. Programmatic Access: information_schema
If you are writing a script or a tool and need to get column names programmatically, you should query the information_schema.columns table.
sql
SELECT column_name, data_type, is_nullable
FROM information_schema.columns
WHERE table_schema = 'your_database_name'
AND table_name = 'your_table_name'
ORDER BY ordinal_position;
* Best for: Automation, filtering for specific columns, or building dynamic SQL.
4. Full Definition: SHOW CREATE TABLE
If you need to see the column names along with their comments, indices, and partitioning logic, use this command:
sql
SHOW CREATE TABLE your_table_name;
* Best for: Seeing the full DDL (Data Definition Language) used to create the table.
5. Including Materialized Views: DESC ... ALL
If you want to see the columns of the base table plus any synchronous materialized views (rollups) associated with it:
sql
DESC your_table_name ALL;
References
• sql-reference/sql-statements/table_bucket_part_index/DESCRIBE.md
• sql-reference/information_schema/columns.md
• faq/Others.md
References
• sql-reference/information_schema/columns.md
• sql-reference/information_schema/tables.md
• faq/Others.md
• sql-reference/sql-statements/table_bucket_part_index/DESCRIBE.md
• table_design/StarRocks_table_design.mdBen Kimpel
05/04/2026, 6:03 PMRocky
05/04/2026, 6:03 PMSELECT COUNT(*) on StarRocks native tables is a "fast count." It doesn't actually scan data; it simply reads the row count stored in the segment metadata of each tablet.
* How to force a scan: Instead of COUNT(*), count a specific column or add a dummy predicate.
sql
-- Forces a scan of the 'id' column
SELECT COUNT(id) FROM your_table;
-- Alternatively, add a filter that must be evaluated
SELECT COUNT(*) FROM your_table WHERE id IS NOT NULL;
2. Disable Query Cache (Result Cache)
The Query Cache stores the final or intermediate results of a query. While it is off by default, you should ensure it's disabled for your session.
sql
SET enable_query_cache = false;
3. Bypass Page Cache (In-Memory Data)
The Page Cache stores recently accessed data blocks in the BE's memory. To force StarRocks to read from the physical disk rather than memory, use the following session variables (available in newer versions like v3.3+):
sql
-- Instructs BEs to bypass the OS/Storage page cache
SET skip_page_cache = true;
-- For older versions, you can try:
SET use_page_cache = false;
4. Bypass Data Cache (For External/Cloud-Native Tables)
If you are querying External Catalogs (Hive, Iceberg, etc.) or using a Shared-Data cluster, StarRocks uses a local "Data Cache" on the BE disks to avoid repeated remote fetches.
sql
-- Instructs the FE to tell BEs to skip the local disk cache
SET skip_local_disk_cache = true;
-- For older versions:
SET enable_scan_datacache = false;
──────────
Summary Checklist for a "Cold" Count
Run these commands in your session before executing your query to ensure a true disk-bound scan:
sql
SET enable_query_cache = false;
SET skip_page_cache = true;
SET skip_local_disk_cache = true;
-- Execute the count on a specific column to avoid metadata-only results
SELECT COUNT(your_primary_key_column) FROM your_table;
Note: Even with these settings, the underlying OS or storage hardware (like a SAN or SSD controller) might still have its own internal caches that StarRocks cannot control.
References
• sql-reference/System_variable.md
• using_starrocks/caching/query_cache.md
• data_source/data_cache.md
• sql-reference/sql-functions/aggregate-functions/count.md
References
• sql-reference/sql-functions/aggregate-functions/count.md
• best_practices/query_tuning/query_planning.md
• knowledge/usage/best-practice.md
• using_starrocks/Cost_based_optimizer.mdBen Kimpel
05/04/2026, 7:13 PMRocky
05/04/2026, 7:14 PMinformation_schema.task_runs history using a DELETE command. The task history is managed automatically by the FrontEnd (FE) based on time and count thresholds.
If you need to clear the history or reduce the number of records, you must adjust the system's global retention settings.
1. How the History is Cleaned
StarRocks uses two main parameters to prune the task history automatically:
* task_runs_ttl_second: (Default: 7 days) How long a task run record is kept before being deleted.
* task_runs_max_history_number: (Default: 10,000) The maximum number of records kept in the history. Once this limit is reached, the oldest records are removed.
2. How to "Force" a Cleanup
If you have thousands of records you want to get rid of immediately, you can temporarily lower these settings to force the FE to prune the history:
sql
-- Reduce the TTL to 1 minute to trigger a cleanup of old runs
ADMIN SET FRONTEND CONFIG ("task_runs_ttl_second" = "60");
-- Or limit the history to a very small number
ADMIN SET FRONTEND CONFIG ("task_runs_max_history_number" = "10");
Important: After the cleanup occurs (it may take a few minutes for the background manager to run), remember to set these back to their default values if you want to keep future history.
3. Does DROP TASK help?
No. Using DROP TASK <task_name> will delete the task definition and cancel any currently RUNNING or PENDING executions, but the historical logs of past runs for that task will still remain in information_schema.task_runs until they expire naturally via the TTL/Max history settings.
Summary of Views
* To see the history: SELECT * FROM information_schema.task_runs;
* To see your settings: ADMIN SHOW FRONTEND CONFIG LIKE '%task_runs%';
References
• administration/management/FE_configuration.md
• sql-reference/information_schema/task_runs.md
• sql-reference/sql-statements/loading_unloading/ETL/DROP_TASK.md
References
• using_starrocks/async_mv/materialized_view_task_run_details.md
• knowledge/usage/best-practice.md
• administration/management/FE_configuration.md
• sql-reference/information_schema/task_runs.md
• data_source/block_cache_warmup.mdBen Kimpel
05/04/2026, 7:26 PMRocky
05/04/2026, 7:26 PMMemUsage reported within DataCacheMetrics (visible via SHOW BACKENDS or SHOW COMPUTE NODES) is determined by the Data Cache (Block Cache) configuration.
The values you are seeing—`DiskUsage: 1.3TB/1.3TB, MemUsage: 15.3GB/15.5GB`—represent the consumption and limits for the caching system used primarily for external catalogs (Data Lake) and shared-data clusters.
How the Max Memory (Denominator) is Determined
The memory limit in DataCacheMetrics is determined by a few key factors:
1. The datacache_mem_size Parameter:
This is the primary BE configuration item that sets the memory limit for the Data Cache. You can find its value by running:
sql
SELECT * FROM information_schema.be_configs WHERE NAME = 'datacache_mem_size';
* If set to a physical limit (e.g., 16G), that value becomes the denominator.
* If set to a percentage (e.g., 10%), it is calculated as a percentage of the total BE process memory limit (mem_limit).
* In newer versions (v3.3+), if this is not explicitly set, the system may use a default internal ratio.
2. Metadata Memory for Block Cache:
In many configurations, the "memory usage" reported here is actually the memory required to maintain the index (metadata) for the data stored on disk.
* StarRocks needs memory to track every ~1MB block stored in the 1.3TB disk cache.
* This metadata usually consumes roughly 1% to 1.5% of the total disk cache size.
_ _Calculation Check:* $1.3\text{ TB} \times 1.2\% \approx 15.6\text{ GB}$. This aligns almost perfectly with your reported $15.5\text{ GB}$ limit.
3. Automatic Scaling (datacache_auto_adjust_enable):
If automatic scaling is enabled (default in some versions), StarRocks dynamically adjusts the cache capacity based on available system memory and disk thresholds (datacache_disk_high_level, etc.).
Why is MemUsage so high (15.3/15.5)?
It is normal for MemUsage to be nearly equal to the limit. Unlike general process memory, the Data Cache memory is often pre-allocated or reserved for the block index. Even if the data isn't being actively "hit," the index must stay in memory to know what is available on the local disks.
How to Adjust It
If you need to increase the memory available for the cache (e.g., to support a larger disk cache or to enable an in-memory data tier), you can modify the configuration:
sql
-- Example: Set memory limit to 20GB dynamically (non-persistent)
ADMIN SET FRONTEND CONFIG ("datacache_mem_size" = "20G");
-- Or via BE config update (recommended to update be.conf as well)
UPDATE be_configs SET VALUE="20G" WHERE NAME="datacache_mem_size";
References
• data_source/data_cache.md
• administration/management/BE_configuration.md
• using_starrocks/caching/block_cache.md
References
• using_starrocks/caching/block_cache.md
• data_source/data_cache.md
• data_source/data_cache_observe.mdBen Kimpel
05/04/2026, 11:57 PMRocky
05/04/2026, 11:57 PMVARCHAR(100) to VARCHAR(10) in StarRocks using the ALTER TABLE ... MODIFY COLUMN statement.
However, there are several important things to keep in mind:
1. Data Truncation Risk
StarRocks allows you to decrease the length of a VARCHAR column, but as the documentation notes, "accuracy loss is guaranteed by the user." This means:
* If you have existing data that is longer than 10 characters, StarRocks will truncate that data to fit the new limit during the schema change process.
* The system will not block the operation just because data is too long; it will perform the truncation to satisfy the new schema.
2. It is an Asynchronous Operation
Changing a column type or length is a "Schema Change" task that runs in the background. The command will return Query OK immediately, but the actual data conversion happens asynchronously.
* Syntax:
sql
ALTER TABLE your_table_name
MODIFY COLUMN your_column_name VARCHAR(10);
* Monitor Progress:
You can check the status of the change using:
sql
SHOW ALTER TABLE COLUMN;
Look for the State column; it will show FINISHED once the migration is complete.
3. Key Column Restrictions
If the column you are modifying is part of the Aggregate Key, Unique Key, or Primary Key, the modification might be more restricted or require specific syntax (e.g., ensuring you specify the KEY keyword or aggregation type if required by your table model). For most Duplicate Key tables, the simple syntax above works fine.
4. Performance Impact
Since shrinking a column length requires re-writing the data files (segments) to validate and truncate the strings, this operation can consume significant CPU and I/O on your BE nodes if the table is very large.
Summary Checklist
* Backup/Verify: Check if you have data longer than 10 characters first: SELECT your_column_name FROM your_table_name WHERE LENGTH(your_column_name) > 10;.
* Execute: Run the ALTER TABLE command.
* Wait: Monitor with SHOW ALTER TABLE COLUMN until the state is FINISHED.
References
• sql-reference/sql-statements/table_bucket_part_index/ALTER_TABLE.md
• sql-reference/data-types/string-type/VARCHAR.md
• knowledge/usage/best-practice.md
References
• knowledge/usage/best-practice.md
• sql-reference/sql-statements/table_bucket_part_index/ALTER_TABLE.md
• sql-reference/data-types/string-type/VARCHAR.md
• sql-reference/System_limit.mdBen Kimpel
05/05/2026, 12:06 AMRocky
05/05/2026, 12:07 AMdate_trunc to automatically create one partition per year.
sql
CREATE TABLE my_table (
event_time DATETIME NOT NULL,
...
)
DUPLICATE KEY(event_time, ...)
PARTITION BY date_trunc('year', event_time) -- Creates 1 partition per year
DISTRIBUTED BY HASH(some_id) BUCKETS 1; -- 1 bucket = 1 tablet of ~1GB
Note: If you have a large cluster (e.g., 10+ nodes) and want to utilize more nodes for a single year's query, you could increase BUCKETS to 5 or 10, but keep the tablet size >100MB.
Option 2: Multi-Year Partitioning
If you have many years of data but the total volume is still small (e.g., 10 years = 10GB), and you want to group them to reduce tablet count further, you can use the time_slice function.
sql
PARTITION BY time_slice(event_time, INTERVAL 5 YEAR)
This would group 5 years of data (approx. 5GB / 275M rows) into a single partition.
──────────
Why Yearly (or Multi-Year) is better for you:
1. Metadata Efficiency: 1 tablet of 1GB is much "cheaper" for the system to manage than 365 tablets of 3MB.
2. I/O Performance: StarRocks reads data in large blocks. With tiny tablets, the system spends more time opening/closing files than actually reading data.
3. 55 Million Rows is "Small": While 55M rows sounds like a lot, at 1GB of storage, these rows are very "narrow" (small byte size per row). Large tablets handle dense, narrow data much more effectively.
When should you NOT do this?
Only use finer partitioning (monthly/daily) if:
* You strictly need to drop/purge data every month (e.g., a rolling 30-day window).
* Your data volume per year grows significantly (e.g., grows from 1GB/year to 100GB/year).
Summary: Stick to PARTITION BY date_trunc('year', event_time). It fits your current 1GB/year profile perfectly.
References
• table_design/data_distribution/expression_partitioning.md
• sql-reference/sql-functions/date-time-functions/date_trunc.mdBen Kimpel
05/05/2026, 12:08 AMRocky
05/05/2026, 12:08 AMBUCKETS 1) is technically ideal from a storage and metadata perspective.
However, in practice, the decision depends on whether you want to prioritize system health (metadata efficiency) or query speed (parallelism). Here is the breakdown of why you might choose one or the other:
1. The "1 Tablet" Approach (Storage Optimized)
If you set BUCKETS 1, you have exactly one tablet of ~1GB.
* Pros: Minimal metadata overhead. StarRocks handles 1GB tablets very efficiently.
* Parallelism: Even with one tablet, StarRocks can use Internal Parallelism (controlled by the session variable enable_tablet_internal_parallel = true). This allows a single BE node to use multiple CPU cores to scan that one tablet.
* Cons: Only one BE node in your cluster will be active when scanning that specific year of data. If you have a 10-node cluster, the other 9 nodes will be idle for that specific partition scan.
2. The "Small Multi-Tablet" Approach (Compute Optimized)
If you set BUCKETS 3 or BUCKETS 5, you would have tablets of ~200MB–330MB.
* Pros: This distributes the year's data across multiple nodes. If you frequently run heavy queries that filter for a single year, this allows 3 or 5 nodes to work on the data simultaneously, which is usually faster than one node.
* Cons: Slightly more metadata. However, at 1GB, even 10 tablets (100MB each) is still well within the "healthy" range for StarRocks.
The Recommended Way: "Auto-Bucketing"
Instead of guessing the number of tablets, the best practice in modern StarRocks (v2.5+) is to omit the bucket count entirely:
sql
CREATE TABLE my_table ( ... )
PARTITION BY date_trunc('year', event_time)
DISTRIBUTED BY HASH(some_id); -- Note: No "BUCKETS X" here
Why this is better:
1. Automatic Scaling: StarRocks will look at your cluster size (number of BEs) and the data volume to pick an optimal number.
2. Growth Support: If your data grows from 1GB/year to 10GB/year in the future, StarRocks will automatically increase the bucket count for new partitions while keeping the old ones small.
Summary
* If you have a small cluster (1–3 nodes): Use BUCKETS 1 or Auto-bucketing. 1GB per tablet is perfect.
* If you have a large cluster (10+ nodes) AND query performance is critical: Use Auto-bucketing or set BUCKETS to a small number like 4 or 8 to ensure the work is spread across more than one machine.
* Avoid: Setting BUCKETS to a high number (like 32 or 64) for such small data, as it will create "fragmented" tablets of 15MB, which degrades performance.
Verdict: For 1GB per year, 1 to 4 tablets is the "sweet spot." Use Auto-bucketing to let the system handle it for you.
References
• best_practices/bucketing.md
• table_design/data_distribution/Data_distribution.md
• faq/Deploy_faq.md
• knowledge/usage/best-practice.mdBen Kimpel
05/05/2026, 12:10 AMRocky
05/05/2026, 12:10 AMCREATE TABLE or when a new partition is added via a routine load or INSERT), StarRocks calculates the bucket count based on the current cluster size and/or previous partition sizes.
* Existing Partitions: If you have 3 nodes and 10 partitions, they will have buckets calculated for 3 nodes. If you add 7 more nodes (total 10), those existing 10 partitions will still have the same number of buckets they were born with.
* New Partitions: Any partition created after you add the nodes will see the new cluster size (10 nodes) and use a higher bucket count automatically.
2. Tablet Balancing vs. Re-bucketing
It is important to distinguish between these two:
* Tablet Balancing (Automatic): When you add nodes, StarRocks will automatically move existing tablets (buckets) to the new nodes to balance the disk usage and query load. However, the total number of tablets for that partition remains the same.
* Re-bucketing (Manual): Changing the number of buckets in an existing partition (e.g., going from 4 tablets to 20 tablets) requires a schema change operation.
3. How to adjust existing tables
If your cluster has grown significantly and you want your old data to take advantage of the new nodes (by increasing the bucket count), you must manually trigger it:
sql
-- This will re-calculate the "auto" bucket count based on current nodes
-- and redistribute the data for all existing partitions.
ALTER TABLE your_table_name DISTRIBUTED BY HASH(your_key);
Note: This is a heavy background operation (Schema Change) as it effectively re-writes the data into the new number of tablets.
4. The Exception: Random Bucketing (v3.2+)
In newer versions, if you use Random Bucketing with the bucket_size property, StarRocks can dynamically increase the number of buckets during a data load if the partition grows beyond the specified size.
* This is volume-based, not node-based.
* It doesn't "shrink" buckets if you add nodes; it just adds more buckets as the data gets bigger.
Summary
* Will it adjust existing data automatically when I add nodes? No.
* Will it adjust new data automatically? Yes, for any partitions created after the nodes were added.
* How do I fix it for old data? Run ALTER TABLE ... DISTRIBUTED BY ... to trigger a manual re-bucketing.
References
• table_design/data_distribution/Data_distribution.md
• administration/management/Control_balance.md
• knowledge/usage/best-practice.md
References
• table_design/data_distribution/Data_distribution.md
• knowledge/usage/best-practice.mdBen Kimpel
05/05/2026, 2:04 AMRocky
05/05/2026, 2:04 AMSHOW PARTITIONS output and lifecycle management become much easier to read and maintain.
🔴 The Cons (What you lose)
1. Coarse-Grained Pruning:
* If you query for "the last 30 days," StarRocks cannot skip the partition. It must open the 10-year partition.
* However: Because your 10-year partition is only ~2 GB, the performance hit is negligible. StarRocks still uses Zone Maps (min/max indexes) inside the files to skip irrelevant data blocks even within a large partition.
2. Difficult Data Retention/Purging:
* If your business requirement is to "Delete data older than 7 years," you cannot use the fast DROP PARTITION command if you have a 10-year chunk. You would have to use a DELETE statement, which is more resource-intensive.
3. Less Node Parallelism (if buckets are low):
* If you set BUCKETS 1 for a 10-year partition, only one node at a time can scan that data (unless using internal parallelism).
──────────
Recommended Implementation
Since your 10-year volume is ~2.1 GB, you should use the time_slice function to define these chunks.
sql
CREATE TABLE my_table (
event_time DATETIME NOT NULL,
...
)
DUPLICATE KEY(event_time)
PARTITION BY time_slice(event_time, INTERVAL 10 YEAR) -- Groups into 10-year buckets
DISTRIBUTED BY HASH(some_id) BUCKETS 3; -- 3 buckets = ~700MB per tablet
The "Golden Rule" for your volume:
* Don't go smaller than Yearly: Anything smaller (Monthly/Daily) will create "tiny tablet syndrome" (tablets < 10MB), which will eventually slow down your cluster.
* 10-Year vs 1-Year:
* If you need to delete data annually: Use Yearly.
* If you rarely delete data and want maximum performance: Use 10-Year chunks.
Rocky's Verdict: Given your tiny annual volume, 10-year chunks are excellent. You avoid the metadata bloat of small partitions while keeping the total data size (2.1 GB) small enough that query performance will still be lightning-fast.
References
• best_practices/partitioning.md
• best_practices/query_tuning/schema_tuning.md
• table_design/data_distribution/Data_distribution.md
• faq/Deploy_faq.md
• best_practices/bucketing.mdBen Kimpel
05/05/2026, 3:19 AMBen Kimpel
05/05/2026, 3:37 AM