Minn Fong
07/08/2026, 7:30 PMcache select feature every time i change my CN Nodes or need to restart them? right now the volume of data for datacache configured partition duration (5 days) is too long, exceeding timeout. Right now my data volume is 1.460TBRocky
07/08/2026, 7:31 PMCACHE SELECT feature is essentially a specialized query that reads data from remote storage and writes it to the local Data Cache. Because it is implemented as a synchronous query (internally using INSERT INTO BLACKHOLE), it is subject to standard query timeouts and resource limits.
To warm up 1.46 TB of data across CN nodes without hitting timeouts, you should use the following strategies:
1. Use SUBMIT TASK for Background Execution
Instead of running CACHE SELECT directly in your SQL client (which can time out due to the client connection or the query_timeout variable), submit it as a background task. Tasks have a much higher default timeout (task_runs_timeout_second is 4 hours) and do not depend on an active client connection.
sql
SUBMIT TASK warmup_task
PROPERTIES (
"session.query_timeout" = "28800", -- 8 hours
"session.pipeline_dop" = "16" -- Adjust based on CN core count
)
AS
CACHE SELECT * FROM your_table
WHERE date_col >= '2023-10-01';
2. Increase Query Timeouts
If you prefer running it synchronously, you must increase the session timeout before executing the statement. For StarRocks v3.4+, use `insert_timeout`; for older versions, use query_timeout.
sql
-- For v3.4 and later
SET insert_timeout = 28800;
-- For versions prior to v3.4
SET query_timeout = 28800;
CACHE SELECT * FROM your_table WHERE ...;
3. Incremental Warmup (Partitioned Approach)
Warming up 1.46 TB in a single statement is prone to failure and can saturate cluster resources. It is highly recommended to split the 5-day duration into smaller chunks (e.g., 6-hour or 12-hour intervals) using the WHERE clause.
* Example Strategy: Submit multiple tasks, each covering a portion of the data.
sql
-- Warm up Day 1
SUBMIT TASK warmup_day1 AS CACHE SELECT * FROM table WHERE dt = '2023-10-01';
-- Warm up Day 2
SUBMIT TASK warmup_day2 AS CACHE SELECT * FROM table WHERE dt = '2023-10-02';
This reduces the blast radius of a single failure and allows you to monitor progress more effectively.
4. Optimize Parallelism
You can speed up the warmup process by increasing the Degree of Parallelism (DOP).
* Set pipeline_dop in your session or task properties to a higher value (e.g., equal to the number of CPU cores on your CN nodes) to maximize disk I/O and network throughput.
5. Managing CN Node Changes
When you add or remove CN nodes, the consistent hashing for Data Cache shifts, causing some data to be reassigned to different nodes.
* Best Practice: After a cluster scaling event or a full restart, prioritize warming up the most "hot" data (e.g., the last 24 hours) first using a high-priority task, then proceed with the rest of the 5-day window in chunks.
Monitoring Progress
You can monitor the status and performance of your warmup tasks using:
sql
-- Check task status
SELECT * FROM information_schema.task_runs WHERE task_name = 'warmup_task' ORDER BY create_time DESC;
-- Use verbose mode in manual queries to see per-node metrics
CACHE SELECT * FROM table PROPERTIES("verbose" = "true") WHERE ...;
Note: Ensure your datacache.partition_duration and the actual disk space allocated for cache (starlet_star_cache_disk_size_percent) are sufficient to hold 1.46 TB. If the cache disk is full, new data will evict the data you just warmed up based on the SLRU policy.
References
• sql-reference/sql-statements/loading_unloading/ETL/SUBMIT_TASK.md
• sql-reference/System_variable.md
• administration/management/FE_configuration.md
• administration/management/resource_management/query_queues.mdMinn Fong
07/08/2026, 7:35 PMRocky
07/08/2026, 7:35 PM_statistics_ database in a PREPARE state indicates that StarRocks' internal automatic statistics collection is hanging or running slower than the trigger interval (default 5 minutes). This is common when the cluster is under heavy resource pressure (like your 1.46TB cache warming) or if the internal _statistics_ tables have too many versions or tablet issues.
To resolve this and stop the transaction count from climbing, follow these steps:
1. Stop the "Bleeding" (Disable Auto-Collection)
Disable the automatic statistics collection mechanism globally to prevent new transactions from being created.
sql
-- Disable automatic full statistics collection
SET GLOBAL enable_collect_full_statistic = false;
-- Disable general automatic statistics collection (v3.1+)
SET GLOBAL enable_auto_collect_statistics = false;
2. Identify and Kill Running Analyze Jobs
Check which tables are currently being analyzed and kill the active tasks.
sql
-- View current and historical analyze jobs
SHOW ANALYZE STATUS;
-- If you see 'RUNNING' jobs, kill them using their ID from the output above
KILL ANALYZE <analyze_job_id>;
3. Clear Stuck Transactions
The transactions you see in PREPARE are likely internal INSERT tasks. Since they have a TimeoutMs of 3,600,000 (1 hour), they will eventually abort on their own, but you can manually cancel them using their labels:
sql
-- Cancel specific stuck insert jobs
CANCEL LOAD FROM _statistics_ WHERE LABEL = "insert_019f4338-a10b-7f8b-bcae-e8e6b6e48162";
Note: If there are hundreds, it is usually better to wait for the 1-hour timeout after disabling the global variables in Step 1.
4. Investigate the _statistics_ Database Health
If these transactions frequently get stuck, the _statistics_ tables themselves might be unhealthy (e.g., too many metadata versions).
* Check tablet health: Run SHOW TABLE STATUS FROM _statistics_; and check for high DataSize or issues.
* Check FE Logs: Search fe.log for keywords like StatisticExecutor or transaction manager is full to see why the PREPARE phase is failing to move to COMMITTED.
Summary of Recommendations
* During Cache Warming: Keep enable_collect_full_statistic set to false until your manual CACHE SELECT operations are complete. Heavy I/O from warming 1.46TB of data can cause the internal statistics DMLs to time out.
* After Cluster Stability: Once the CN nodes are stable and data is cached, re-enable statistics collection if needed, but consider increasing the interval or using SAMPLE collection for large tables to reduce overhead.
References
• knowledge/trouble_shooting/fe_deadlock_problems.mdMinn Fong
07/08/2026, 7:39 PMRocky
07/08/2026, 7:40 PMenable_statistic_collect and enable_collect_full_statistic are FE Configuration Items, not system variables. They cannot be modified using SET GLOBAL.
To stop the climbing transactions and disable automatic statistics collection, use the ADMIN SET CONFIG command:
1. Disable Statistics Collection (Correct Commands)
Run these commands to turn off the background statistics tasks immediately:
sql
-- Disable the main statistics collection switch
ADMIN SET CONFIG ("enable_statistic_collect" = "false");
-- Disable full statistics collection
ADMIN SET CONFIG ("enable_collect_full_statistic" = "false");
-- (Optional) Disable collection triggered by new data loads (v3.1+)
ADMIN SET CONFIG ("enable_statistic_collect_on_first_load" = "false");
2. Kill Active Analyze Jobs
Even after disabling the config, currently running jobs may keep transactions open. Check and kill them:
sql
-- View running jobs
SHOW ANALYZE STATUS;
-- Kill any job in 'RUNNING' state
KILL ANALYZE <job_id>;
3. Why are transactions "climbing"?
The INSERT_STREAMING transactions you see in _statistics_ are internal StarRocks tasks trying to write metadata to system tables. They are likely stuck in PREPARE because:
* Resource Contention: Your 1.46TB cache warming is likely saturating the disk I/O or network, preventing the metadata transactions from committing.
* Metadata Lock: The statistics update requires a lock on the _statistics_ database/tables. If a previous job is hung or your cache warming query is holding a wide lock, new statistics jobs will queue up indefinitely.
4. How to clear the existing 292,000+ transactions
Since these are internal transactions, they will stay in the PREPARE state until they hit their TimeoutMs (shown as 3,600,000ms or 1 hour in your table).
* Immediate fix: Once you run the ADMIN SET CONFIG commands above, no new transactions will be created.
* Cleanup: The existing ones will eventually move to ABORTED once they time out. You do not typically need to manually cancel 200k transactions one by one; the system will clear them automatically after the 1-hour window.
Recommendation for your Cache Warming
When performing a large-scale CACHE SELECT (1.4TB+):
1. Always disable stats collection first using the ADMIN commands above.
2. Break the warmup into smaller batches (e.g., partition by partition) to avoid long-running transactions that can interfere with FE metadata health.
3. Re-enable stats collection only after the warmup is finished and the cluster load has stabilized.
References
• using_starrocks/Cost_based_optimizer.md
• administration/management/FE_configuration.md
• sql-reference/sql-statements/cluster-management/config_vars/ADMIN_SET_CONFIG.md
References
• knowledge/trouble_shooting/fe_deadlock_problems.md
• loading/loading_introduction/troubleshooting_loading.mdMinn Fong
07/08/2026, 7:52 PMselect * is blocking transactions
Root cause
A SQL blacklist rule is silently breaking the internal statistics housekeeping loop.
The offending rule (SHOW SQLBLACKLIST):
Id: 0
Forbidden SQL: (?i)select\s+\*\s+from\s+.+
enable_sql_blacklist = true. This regex blocks every SELECT * FROM <anything> statement cluster-wide. It was added at ~18:44 today (first rejection: 18:44:32), which lines up exactly with when the stuck transactions began piling up (oldest running txn 18:47).
The mechanism (from the FE journal, thread Load history syncer|61, once every 60s at :32):
1. The syncer daemon fires INSERT INTO _statistics_.loads_history SELECT * FROM information_schema.loads WHERE ...
2. beginTransaction runs first → txn enters PREPARE
3. The blacklist check then rejects the statement: This sql is in blacklist (id: 0) — because the INSERT's body contains SELECT * FROM information_schema.loads
4. The rejection path never aborts the already-begun transaction → it's orphaned in PREPARE (never reaches PREPARED/COMMITTED, hence all the NULL timestamps)
5. Repeats every minute → 61 accumulated
How can i fix it? Make it particular to db?
SO blacklist select * from requests and select * from requests.requestsRocky
07/08/2026, 7:52 PMsql
-- Remove the problematic global rule
DELETE SQLBLACKLIST 0;
Once the rule is deleted, the internal syncer daemon will stop creating orphaned transactions. The existing 292,000+ transactions will eventually time out (based on their TimeoutMs, usually 1 hour) and clear themselves. If the FE's memory or performance is severely impacted, a rolling restart of the FEs would clear the transaction manager immediately.
2. Refine the Blacklist for the requests table
To block SELECT _ only for your specific table and its fully qualified name, use a more restrictive regex. This prevents matching internal queries like SELECT _ FROM information_schema.loads.
Run this command to target the requests table specifically:
sql
-- Targets 'requests' or 'requests.requests' specifically
ADD SQLBLACKLIST "(?i)select\\s+\\*\\s+from\\s+(requests|requests\\.requests)(\\s+|$|;)";
*3. (Alternative) Block SELECT * for everything EXCEPT system DBs*
If you want to maintain a general ban on SELECT * for all user tables but allow StarRocks to perform its internal tasks, use a negative lookahead to ignore system databases (_statistics_, information_schema, etc.):
sql
-- Blocks SELECT * from any table UNLESS it starts with information_schema or _statistics_
ADD SQLBLACKLIST "(?i)select\\s+\\*\\s+from\\s+(?!(information_schema|_statistics_))\\S+";
Why this happened
In StarRocks, when a SQL blacklist rule matches an internal query (like the stats syncer):
1. The transaction is started (State: PREPARE).
2. The blacklist check fails.
3. Because the rejection happens during the analysis phase of an internal background task, the transaction isn't always explicitly aborted by the daemon, leaving it "orphaned" until it hits the 1-hour TimeoutMs.
Recommendation: Always use SHOW SQLBLACKLIST after adding a rule and test it with a manual query to ensure it doesn't accidentally catch system keywords.
References
• administration/management/resource_management/Blacklist.md
• sql-reference/sql-statements/cluster-management/sql_blacklist/ADD_SQLBLACKLIST.md
• sql-reference/sql-statements/cluster-management/sql_blacklist/DELETE_SQLBLACKLIST.md
References
• administration/management/resource_management/Blacklist.md
• sql-reference/sql-statements/cluster-management/sql_blacklist/DELETE_SQLBLACKLIST.md
• sql-reference/sql-statements/cluster-management/nodes_processes/DELETE_BACKEND_BLACKLIST.md
• sql-reference/sql-statements/cluster-management/sql_blacklist/ADD_SQLBLACKLIST.md
• administration/management/monitor_manage_big_queries.mdMinn Fong
07/08/2026, 8:54 PMshow data from <table> count s3 stored data or only cached data?Rocky
07/08/2026, 8:54 PMSHOW DATA FROM <table_name> counts the total persistent data stored in object storage (S3).
It does not represent the amount of data currently residing in the local disk cache of your Compute Nodes (CN).
Key Distinctions
* Persistent Storage (S3): This is the source of truth for the table's size. When you run SHOW DATA or query information_schema.partitions_meta, the DATA_SIZE column reflects the size of the segment files stored on S3.
* Local Cache: This is a transient copy of "hot" data stored on the CN nodes' local disks for acceleration. The cache size is limited by your CN configurations (e.g., starlet_star_cache_disk_size_percent) and its contents change based on LRU eviction or TTL.
How to verify
You can see the relationship between the data size and the S3 path using the following command:
sql
SHOW PROC '/dbs/<db_id>/<table_id>/partitions';
In the output:
* DataSize: Shows the size of the data in S3.
* StoragePath: Displays the S3 bucket and prefix where this data is persisted.
Monitoring Cache
Standard SQL commands like SHOW DATA do not currently provide a table-by-table breakdown of how much data is "cached" vs "uncached." To monitor the health and performance of your cache, you should look at the CN metrics (typically via Prometheus/Grafana) for:
* `starcache_disk_usage`: Total disk space used by the cache.
* `starcache_read_bytes`: Total bytes read.
* `starcache_skip_read_bytes`: Bytes read directly from S3 (cache misses).
References
• introduction/Architecture.md
• deployment/shared_data/s3.md
• knowledge/admin_and_operation/shared_data_compaction.md
References
• knowledge/admin_and_operation/shared_data_compaction.mdMinn Fong
07/08/2026, 8:55 PMMySQL [(none)]> show compute nodes;
+---------------+--------------+---------------+--------+----------+----------+---------------------+---------------------+-------+----------------------+-----------------------+--------+---------------+----------+----------+-------------------+------------+------------+-----------------------------------------------------------------+----------------+------------+-------------+----------+-------------------+-----------+
| ComputeNodeId | IP | HeartbeatPort | BePort | HttpPort | BrpcPort | LastStartTime | LastHeartbeat | Alive | SystemDecommissioned | ClusterDecommissioned | ErrMsg | Version | CpuCores | MemLimit | NumRunningQueries | MemUsedPct | CpuUsedPct | DataCacheMetrics | HasStoragePath | StatusCode | StarletPort | WorkerId | WarehouseName | TabletNum |
+---------------+--------------+---------------+--------+----------+----------+---------------------+---------------------+-------+----------------------+-----------------------+--------+---------------+----------+----------+-------------------+------------+------------+-----------------------------------------------------------------+----------------+------------+-------------+----------+-------------------+-----------+
| 386018 | 172.30.72.74 | 9050 | 9060 | 8040 | 8060 | 2026-07-06 17:19:22 | 2026-07-08 20:53:18 | true | false | false | | 4.0.7-b75f536 | 8 | 41.702GB | 0 | 40.72 % | 0.4 % | Status: Normal, DiskUsage: 565.7GB/3.3TB, MemUsage: 8.3GB/8.3GB | true | OK | 9070 | 15394 | default_warehouse | 985 |
| 386020 | 172.30.76.86 | 9050 | 9060 | 8040 | 8060 | 2026-07-06 17:19:32 | 2026-07-08 20:53:18 | true | false | false | | 4.0.7-b75f536 | 8 | 41.702GB | 0 | 40.29 % | 0.3 % | Status: Normal, DiskUsage: 593.8GB/3.3TB, MemUsage: 8.3GB/8.3GB | true | OK | 9070 | 15395 | default_warehouse | 984 |
| 386019 | 172.30.88.64 | 9050 | 9060 | 8040 | 8060 | 2026-07-07 19:32:31 | 2026-07-08 20:53:18 | true | false | false | | 4.0.7-b75f536 | 8 | 41.702GB | 0 | 41.04 % | 0.3 % | Status: Normal, DiskUsage: 337.6GB/3.3TB, MemUsage: 8.3GB/8.3GB | true | OK | 9070 | 15393 | default_warehouse | 934 |
+---------------+--------------+---------------+--------+----------+----------+---------------------+---------------------+-------+----------------------+-----------------------+--------+---------------+----------+----------+-------------------+------------+------------+-----------------------------------------------------------------+----------------+------------+-------------+----------+-------------------+-----------+
3 rows in set (0.002 sec)
MySQL [(none)]> show data from events.events;
+-----------+-----------+----------+--------------+------------+
| TableName | IndexName | Size | ReplicaCount | RowCount |
+-----------+-----------+----------+--------------+------------+
| events | events | 1.462 TB | 2704 | 3787697409 |
| | Total | 1.462 TB | 2704 | |
+-----------+-----------+----------+--------------+------------+
2 rows in set (0.001 sec)Rocky
07/08/2026, 8:55 PMDiskUsage in DataCacheMetrics is a node-level metric. If you have any other tables in the cluster, their cached data is also included in that $1497.1\text{ GB}$ total. If this is your only table, the 100% conclusion is solid.
2. Metadata and Overhead: The cache storage includes a small amount of overhead for the cache index and metadata. However, at the TB scale, this is usually negligible.
3. ReplicaCount: In the shared-data architecture, the ReplicaCount (2704) in your SHOW DATA output refers to the total number of tablets (partitions $\times$ buckets). Unlike shared-nothing mode, there is only one physical copy of the data on S3. Each tablet is assigned to a specific CN for caching to avoid duplicate cache entries across nodes.
How to verify with 100% certainty
To confirm that a specific query is reading entirely from the cache without hitting S3, run a SELECT query and check the Query Profile:
1. Run your query: SELECT count(*) FROM events.events;
2. Get the profile: get_query_profile('<query_id>');
3. Look for the Scan Node section. You want to see:
* DataCacheHitBytes should equal the total bytes read.
* RemoteReadBytes (or similar S3 read metrics) should be 0.
* Alternatively, monitor the starcache_hit_ratio metric in Grafana during the query; it should be 1.0.
Summary
You can confidently say the data is cached. The fact that the $1.462\text{ TB}$ is distributed across your 3 nodes ($565\text{ GB}$, $593\text{ GB}$, $337\text{ GB}$) also shows that StarRocks has balanced the tablets across the warehouse for caching.
References
• knowledge/admin_and_operation/shared_data_compaction.mdMinn Fong
07/08/2026, 8:57 PMRocky
07/08/2026, 9:01 PMScanTime in your profile does not mean the data was fetched from S3.
In StarRocks, ScanTime and IOTaskExecTime represent the time spent by the I/O threads reading data, regardless of whether that data comes from the local disk cache or remote S3.
Based on your profile, here is what is actually happening:
1. Verification of Cache Hits
To confirm if it hit S3, you need to look further down in the OLAP_SCAN section of the profile (which was truncated in your message). Look for these specific counters:
* DataCacheReadBytes: If this matches your total read size, it was 100% Cache.
* DataCacheWriteBytes: If this is 0, then no data was fetched from S3 during this query.
2. Why did it take 6 seconds if it's cached?
Even when data is 100% cached on local NVMe/SSD, a query can take several seconds for these reasons:
* CreateSegmentIter (4.12s): This is the biggest bottleneck in your profile. It represents the time spent opening segment files and initializing the iterators. Because you have 2,704 tablets and likely many more segment files, the overhead of opening thousands of local files adds up.
* Full Column Scan: Your query is min(request_time). If request_time is not the first column in your DUPLICATE KEY (the Sort Key), StarRocks must scan the entire request_time column across all 3.7 billion rows to find the minimum value.
* Aggregation Overhead: Although min() is simple, it still requires reading the data into memory, handling nulls, and performing the comparison across 98,304 internal chunks (as seen in your OutputRows from the scan node).
3. How to speed this up
If you need this specific query to be faster:
1. Check the Sort Key: Ensure request_time is the first column in your PROPERTIES("short_key" = "...") or the first column in your table definition. If it is the primary sort key, StarRocks can find the min by just looking at the first block of the first segment, making it near-instant.
2. Tablet Count: 2,704 tablets for a 1.5TB table is reasonable, but if you have thousands of small files per tablet (check show fragments from events), consider triggering a compaction to reduce the CreateSegmentIter overhead.
3. Use a Materialized View: If you frequently query the min/max of this table, an asynchronous Materialized View can pre-aggregate this value.
Summary: Your query is likely running entirely from the local cache. The 6-second latency is caused by the overhead of processing 3.7 billion rows across thousands of file segments, not S3 network latency.
References
• data_source/data_cache.md
• best_practices/query_tuning/query_profile_operator_metrics.md
References
• data_source/data_cache.md
• best_practices/query_tuning/query_profile_operator_metrics.md
• administration/management/resource_management/Blacklist.md
• sql-reference/sql-statements/cluster-management/sql_blacklist/ADD_SQLBLACKLIST.md
• sql-reference/sql-statements/cluster-management/sql_blacklist/DELETE_SQLBLACKLIST.md
• administration/management/monitor_manage_big_queries.md
• introduction/Architecture.md
• deployment/shared_data/s3.mdRocky
07/08/2026, 9:01 PMRocky
07/08/2026, 9:01 PMRocky
07/08/2026, 9:01 PMRocky
07/08/2026, 9:01 PMRocky
07/08/2026, 9:01 PMRocky
07/08/2026, 9:01 PMRocky
07/08/2026, 9:01 PMRocky
07/08/2026, 9:01 PMRocky
07/08/2026, 9:01 PMMinn Fong
07/08/2026, 9:04 PMrequest_time, auction_id, imp_key)
COMMENT "OLAP"
PARTITION BY date_trunc('hour', request_time)
DISTRIBUTED BY HASH(auction_id) BUCKETS 16
ORDER BY(request_time, auction_id)
PROPERTIES (
"compression" = "ZSTD",
"datacache.enable" = "true",
"datacache.partition_duration" = "5 days",
"enable_async_write_back" = "false",
"enable_persistent_index" = "true",
"file_bundling" = "true",
"partition_live_number" = "168",
"persistent_index_type" = "CLOUD_NATIVE",
"replication_num" = "1",
"storage_volume" = "core_services_volume"
);
This is my table property.
Each partition is approximately 10 gigabytes with 16 buckets.Rocky
07/08/2026, 9:05 PMOLAP_SCAN section:
* `DataCacheWriteBytes`: If this is 0, then no data was downloaded from S3 during the query.
* RemoteReadBytes or `CompressedBytesReadRemote`: These should also be 0 if you are 100% cached.
The 6-second "ScanTime" in the profile is a measurement of the I/O pipeline duration, which includes reading from your local NVMe/SSD cache. In StarRocks, "Scan" refers to the process of retrieving data from the storage layer (local or remote).
2. Why 6 seconds for a "simple" Min()?
In a shared-data Primary Key table, a min() query is not a simple metadata lookup because of the Primary Key (Delete+Insert) Architecture.
* Row Visibility (DelVector): Unlike a Duplicate Key table, a Primary Key table must check the DelVector (delete markers) for every row to ensure that the minimum value you find hasn't been deleted or updated by a newer version. This prevents a "short-circuit" optimization where StarRocks simply looks at the first block of the first segment.
* CreateSegmentIter (4.12s): This is your main bottleneck. It is the time spent opening the thousands of segment files across your 2,704 tablets.
* With 168 partitions and 16 buckets, you have ~2,700 tablets.
* Each node is managing ~900 tablets.
* Opening and initializing the iterators for 900 tablets (and their associated segments and delete vectors) takes several seconds, even if the data is local.
3. Analysis of your Table Design
Your table design is quite good, but there are two factors contributing to the latency:
* Tablet Granularity: You have ~2,700 tablets for 1.5TB, which is ~550MB per tablet. For massive scans, StarRocks generally performs better with larger tablets (1GB–10GB). Having so many "small" tablets increases the metadata overhead and the CreateSegmentIter time.
* Persistent Index: You are using CLOUD_NATIVE persistent indexes. While these are cached locally, StarRocks still needs to verify the index state during the scan to handle the Primary Key logic.
Recommendations for Optimization
If you need this query to be sub-second:
1. Reduce Buckets: If you don't need 16 buckets for every hourly partition (e.g., if you don't query just one hour at a time), consider reducing BUCKETS to 4 or 8. This will reduce the total tablet count and the CreateSegmentIter overhead.
2. Trigger Compaction: High CreateSegmentIter time often points to many small "rowsets" (versions of data). Check the version count:
sql
SHOW TABLET FROM events.events;
If VersionCount is high (>10-20), the system is doing a "merge-on-read" of many small files. Increasing compaction aggressiveness can help.
3. Use a Materialized View: Since you are using a Primary Key table, you can create a synchronous or asynchronous Materialized View to pre-calculate the min(request_time) if this is a high-frequency query.
Summary: Your data is 100% cached. The 6 seconds is the "cost of doing business" for a Primary Key table ensuring data consistency across 3.7 billion rows and 2,700 tablets.