Cold starts slow down your first analytical queries: compute nodes must fetch columnar data from remote Object Storage Service (OSS), which adds I/O latency before any results are returned. Cache prefetching eliminates this by loading the data you need into the columnar read-only instance cache before queries run, on a schedule you define.
How it works
PolarDB-X uses a compute-storage separation architecture. By default, compute nodes check the local cache first. On a cache miss, the columnar engine fetches data from OSS and backfills it into the cache hierarchy — this is passive mode.
Cache prefetching adds an active mode: the WARMUP statement pushes specified columnar data into the cache on a schedule you control. The two modes work together:
| Mode | Trigger | Mechanism |
|---|---|---|
| Passive (cache management) | Query-driven | Fetches data on a cache miss, then backfills up the cache hierarchy |
| Active (cache prefetching) | Schedule-driven | Preloads target data before queries arrive, using the WARMUP statement |
Instance support
Cache prefetching is supported on columnar read-only instances and on primary instances that have an attached columnar read-only instance.
When you run
WARMUPon the primary instance, it is forwarded to the columnar read-only instance. The primary instance acts as a proxy only.
Usage notes
Prefetch scope
All valid SQL query statements (such as
SELECT) are supported.Only the data blocks (columnar files and indexes) specified in the SQL statement are prefetched — not all data associated with the queried tables.
Prefetched data is evicted by the same unified eviction mechanism that manages the columnar engine cache.
Write precise SQL
Target only the data you need. A full table scan wastes cache on data that may never be queried.
-- Efficient: loads only data for the specified date
SELECT * FROM orders WHERE date = '2023-10-01';
-- Inefficient: pulls the entire table
SELECT * FROM orders;Task scheduling
Multiple prefetching tasks scheduled for the same time window are queued and executed in the order they are initiated.
Schedule prefetching during off-peak hours (such as early morning) to minimize the impact on real-time queries.
Prefetch only the core tables and time ranges that your high-frequency queries actually use.
Use cases
Cache prefetching suits stable, predictable query patterns. It is not suitable for ad hoc queries, which vary too much to benefit from a fixed prefetching schedule.
Syntax
WARMUP [cron_expression]
SELECT
select_expr [, select_expr] ...
[FROM table_references]
[WHERE where_condition]
[GROUP BY {col_name | expr | position} [ASC | DESC], ...]
[HAVING where_condition]
[ORDER BY {col_name | expr | position} [ASC | DESC], ...]
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
cron_expression:
('cron_string') | <empty>
select_expr:
column_name
| aggregate_function(column_name)
| column_name AS alias_name
| expressionTo run multiple SELECT statements in a single WARMUP call, enclose each in braces ({ }):
WARMUP [cron_expression]
{SELECT ...}
{SELECT ...}
{SELECT ...};Parameters
| Parameter | Required | Type | Description |
|---|---|---|---|
WARMUP | - | - | The cache prefetching keyword. |
cron_expression | No | String | A Linux crontab (CRON) schedule expression. If omitted, the prefetch runs once immediately. |
select_expr | Yes | — | The column or expression to prefetch. Accepts a column name, aggregate function, alias, or expression. |
FROM table_references | Yes | — | The table to prefetch data from. |
WHERE where_condition | No | — | A filter to limit the data range that is prefetched. |
GROUP BY | No | — | Groups the result set by the specified columns. |
HAVING where_condition | No | — | Filters grouped results. |
ORDER BY | No | — | Sorts the result set. |
LIMIT | No | — | Limits the number of rows or defines an offset. |
CRON expression format
A CRON expression has five space-separated fields:
| Field | Position | Accepted values |
|---|---|---|
| Minute | 1st | 0–59 |
| Hour | 2nd | 0–23 |
| Day of month | 3rd | 1–31 |
| Month | 4th | 1–12, or JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC |
| Day of week | 5th | 0–7, or SUN, MON, TUE, WED, THU, FRI, SAT (both 0 and 7 represent Sunday) |
Special characters:
| Character | Meaning | Example |
|---|---|---|
* | Matches all values | * * * * * — every minute |
, | Enumerates multiple values | 3,15 * * * * — the 3rd and 15th minute of every hour |
- | Specifies a range | 0 9-17 * * * — every hour from 9 AM to 5 PM |
/ | Specifies an increment | */2 * * * * — every 2 minutes |
? | Matches any value | Used in the day-of-month or day-of-week field |
L | Last day of the month | 0 0 L * * — midnight on the last day of every month |
Examples
When WARMUP has no CRON expression, the prefetch runs immediately. When a CRON expression is included, the prefetch runs on the defined schedule.
The following examples use the TPC-H 100 GB test dataset. For details, see TPC-H tests.
Prefetch immediately
WARMUP SELECT * FROM lineitem;Prefetch every 3 minutes
WARMUP('*/3 * * * *')
SELECT *
FROM lineitem
WHERE l_shipdate > '2024-09-01';Prefetch daily at 8 AM
WARMUP('0 8 * * *')
SELECT *
FROM lineitem, part
WHERE l_partkey = p_partkey;Prefetch within a time window
The following statement runs every 5 minutes between 1 AM and 5 AM each day:
WARMUP('*/5 1-5 * * *')
SELECT *
FROM lineitem, part
WHERE l_partkey = p_partkey;Manage prefetching tasks
View scheduled tasks
Query information_schema.columnar_warmup to list all scheduled prefetching tasks. Tasks created without a CRON expression (immediate, one-time prefetches) are not included.
-- List all scheduled tasks in the database named database1
SELECT * FROM information_schema.columnar_warmup WHERE schema_name = 'database1';Fields returned:
| Field | Description |
|---|---|
ID | Primary key |
TASK_ID | Task ID |
SCHEMA_NAME | Database name |
CREATE_TIME | Creation time |
CRON_EXPR | CRON expression |
SQL_DEF | The SQL statement used for prefetching |
STATUS | VALID — the task is scheduled. INVALID — the task is no longer scheduled, typically because the SQL became invalid after a column change. |
View execution history
Query information_schema.warmup_execution_logs to review past prefetch runs.
-- Show executions from the past 2 days
SELECT * FROM information_schema.warmup_execution_logs
WHERE start_time >= NOW() - INTERVAL 2 DAY;Fields returned:
| Field | Description |
|---|---|
ID | Primary key |
TASK_ID | Task ID |
TRACE_ID | Execution record number for the prefetching SQL |
START_TIME | Start time |
FINISH_TIME | End time |
TIME_COST | Execution duration, in milliseconds |
IO_MESSAGE | I/O details |
Delete tasks
Find the TASK_ID in information_schema.columnar_warmup, then run:
-- Delete a specific task
WARMUP DELETE <TASK_ID>
-- Delete all tasks
WARMUP DELETE ALL;Pause and resume tasks
-- Pause a specific task
WARMUP SUSPEND <TASK_ID>
-- Pause all tasks
WARMUP SUSPEND ALL;
-- Resume a specific task
WARMUP RESUME <TASK_ID>
-- Resume all tasks
WARMUP RESUME ALL;Best practices
Choose a prefetching strategy based on your query pattern:
High-write workloads with low-latency requirements — Schedule prefetching on commonly used columns of the target table every 2 minutes to keep the cache fresh after writes:
WARMUP('*/2 * * * *')
SELECT col1, col2, col3 FROM <table_name>;Scheduled analytical reports — If your analytics job runs at 22:00 every day, schedule a prefetch 30 minutes earlier to warm the cache:
WARMUP('30 21 * * *')
SELECT col1, col2, col3
FROM <table_name1>
LEFT JOIN <table_name2> ON <table_name1>.id1 = <table_name2>.id2
LEFT JOIN <table_name3> ON <table_name1>.id1 = <table_name3>.id3
WHERE <table_name1>.col_date > '2024-01-01';Performance benchmarks (TPC-H, ClickBench) — Run a one-time prefetch across all tables before testing to eliminate cold-start variance from results:
WARMUP SELECT * FROM lineitem;
WARMUP SELECT * FROM orders;
WARMUP SELECT * FROM customer;
WARMUP SELECT * FROM part;
WARMUP SELECT * FROM partsupp;
WARMUP SELECT * FROM supplier;
WARMUP SELECT * FROM region;
WARMUP SELECT * FROM nation;Maintenance windows — Use a time-bounded CRON expression to confine prefetching to off-peak hours:
WARMUP('*/5 1-5 * * *')
SELECT * FROM lineitem;