Skip to content

Commit 1d3b68f

Browse files
authored
Issue 469 mutable ttl (#508)
1 parent 1d87100 commit 1d3b68f

File tree

4 files changed

+135
-7
lines changed

4 files changed

+135
-7
lines changed

docs/materialized-view.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ AS
6767
[COMMENT '<comments>']
6868
```
6969

70-
Example
70+
### Example
7171

7272
```sql
7373
-- Create a source stream
@@ -97,7 +97,7 @@ SELECT * FROM aggr_results;
9797

9898
:::info
9999
A **Materialized View** is always bound to a **streaming `SELECT` query**.
100-
If you want to materialize a **historical query** on a schedule, consider using a [Timeplus scheduled task](/task) instead.
100+
If you want to materialize a **historical query** on a schedule, consider using a [**Timeplus scheduled task**](/task) instead.
101101
:::
102102

103103
### Settings

docs/mutable-stream-ttl.md

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# TTL
2+
3+
TTL for Mutable Streams works differently from [Append Stream](/append-stream-ttl) because data is row-encoded.
4+
5+
Mutable Streams evaluate the timestamp of each row in the historical store asynchronously during background data merge or compaction of the key space. Expired rows are automatically garbage-collected when their TTL elapses.
6+
7+
:::info
8+
A Mutable Stream created without a TTL cannot be altered later to support TTL, and similarly, a stream with TTL cannot have TTL removed.
9+
:::
10+
11+
## Retention Based on Wall Clock
12+
13+
In this mode, you specify the storage setting `ttl_seconds` with a non-zero value.
14+
15+
When a row is inserted, the system automatically assigns a **wall-clock timestamp** to it.
16+
If a row has not been updated for longer than `ttl_seconds`, it becomes **eligible for garbage collection** during background compaction.
17+
18+
### Syntax
19+
20+
```sql
21+
CREATE MUTABLE STREAM ...
22+
SETTINGS
23+
ttl_seconds=<ttl-seconds>, ...
24+
```
25+
26+
### Example
27+
28+
```sql
29+
CREATE MUTABLE STREAM ttl_cached(
30+
id string,
31+
name string,
32+
price string,
33+
description string,
34+
event_time datetime
35+
)
36+
PRIMARY key id
37+
SETTINGS
38+
ttl_seconds = 3600;
39+
```
40+
41+
In this example, each row is assigned a **TTL of 1 hour** (3600 seconds).
42+
If a row is not updated within that time window, it will be **automatically removed** during the next background compaction.
43+
44+
## Retention Based on Event Timestamp
45+
46+
In this mode, you must specify both the storage settings `ttl_seconds` (a non-zero value) and `ttl_column`.
47+
48+
The specified **TTL column** represents the event timestamp of each row. During background compaction, the system evaluates this column to determine whether the row has expired and should be garbage-collected.
49+
50+
### Syntax
51+
52+
```sql
53+
CREATE MUTABLE STREAM ...
54+
SETTINGS
55+
ttl_seconds=<ttl-seconds>,
56+
ttl_column=<ttl-column>, ...
57+
```
58+
59+
### Example
60+
61+
```sql
62+
CREATE MUTABLE STREAM event_ttl_cached(
63+
id string,
64+
name string,
65+
price string,
66+
description string,
67+
event_time datetime
68+
)
69+
PRIMARY key id
70+
SETTINGS
71+
ttl_seconds = 3600,
72+
ttl_column = 'event_time';
73+
```
74+
75+
In this example, the stream is configured with a **TTL of 1 hour**.
76+
If `now() - event_time >= 3600`, the row is considered **expired** and will be **garbage-collected** during background compaction.
77+
78+
## Controlling TTL Frequency
79+
80+
TTL evaluation occurs during background **merge** or **compaction** operations.
81+
You can control how frequently these compactions run by setting `periodic_compaction_seconds` in `kvstore_options`.
82+
83+
**Example:**
84+
85+
```
86+
CREATE MUTABLE STREAM ...
87+
SETTINGS
88+
ttl_seconds = <ttl-seconds>,
89+
ttl_column = <ttl-column>,
90+
kvstore_options = 'periodic_compaction_seconds=1800;';
91+
```
92+
93+
In this example, the storage engine is configured to trigger periodic compaction every **30 minutes** (1800 seconds), which indirectly determines how often expired rows are cleaned up.
94+
95+
## Manually Triggering Compaction
96+
97+
Expired data is removed only during background compaction.
98+
If you want to accelerate TTL cleanup, you can manually trigger compaction using the `OPTIMIZE` command.
99+
100+
```sql
101+
OPTIMIZE STREAM <db.stream-name>;
102+
```
103+
104+
This command initiates an immediate, unscheduled merge or compaction for the specified stream, helping reclaim space and remove expired rows sooner.

docs/mutable-stream.md

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ SETTINGS
4040
logstore_retention_bytes=<retention-bytes>,
4141
logstore_retention_ms=<retention-ms>,
4242
ttl_seconds=<ttl-seconds>,
43+
ttl_column=<ttl-column>,
4344
auto_cf=[true|false],
4445
placement_policies='<placement-policies>',
4546
late_insert_overrides=[true|false],
@@ -58,23 +59,35 @@ SETTINGS
5859
enable_statistics=[true|false];
5960
```
6061

62+
### Example
63+
64+
```sql
65+
CREATE MUTABLE STREAM products(
66+
id string,
67+
name string,
68+
price float32,
69+
description string
70+
)
71+
PRIAMRY KEY id;
72+
```
73+
6174
### Storage Architecture
6275

6376
Each shard in a Mutable Stream has [dural storage](/architecture#dural-storage), consisting of:
6477

6578
- Write-Ahead Log (WAL), powered by NativeLog. Enabling incremental processing.
6679
- Historical key-value store, powered by RocksDB.
6780

68-
Data is first ingested into the WAL, and then asynchronously committed to the row store in large batches.
81+
Data is first ingested into the WAL, and then asynchronously committed to the row store in large batches.
6982

7083
The Mutable Stream settings allow fine-tuning of both storage layers to balance performance, durability, and efficiency.
7184

7285
### PRIMARY KEY
7386

74-
**PRIMARY KEY** — Defines the uniqueness of a row in a Mutable Stream. **Required.**
87+
**PRIMARY KEY** — Defines the uniqueness of a row in a Mutable Stream. **Required.**
7588

76-
Rows are organized and sorted based on the primary key, and the primary index is built on top of it.
77-
See [Mutable Stream Indexes](/mutable-stream-indexes) for more details.
89+
Rows are organized and sorted based on the primary key, and the primary index is built on top of it.
90+
See [Mutable Stream Indexes](/mutable-stream-indexes) for more details.
7891

7992
### Secondary Indexes
8093

@@ -139,10 +152,16 @@ Garbage collection runs periodically in the background (default: every 5 minutes
139152

140153
#### `ttl_seconds`
141154

142-
Retention policy for the **historical key-value store (RocksDB)** based on ingest time (wall clock). When a row exceeds this threshold, it is eligible for deletion. Garbage collection is background and **non-deterministic**, so do not rely on exact deletion timing.
155+
Refer [Mutable Stream TTL](/mutable-stream-ttl) for details.
143156

144157
**Default**: `-1` (no retention)
145158

159+
#### `ttl_column`
160+
161+
Refer [Mutable Stream TTL](/mutable-stream-ttl) for details.
162+
163+
**Default**: `""`
164+
146165
#### `auto_cf`
147166

148167
Automatically groups columns of similar type/characteristics into column families.

sidebars.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,11 @@ const sidebars = {
354354
id: "mutable-stream-coalesced",
355355
label: "Coalesced Mutable Stream",
356356
},
357+
{
358+
type: "doc",
359+
id: "mutable-stream-ttl",
360+
label: "TTL",
361+
},
357362
]
358363
},
359364
{

0 commit comments

Comments
 (0)