Skip to main content

risingwave_common/config/
meta.rs

1// Copyright 2025 RisingWave Labs
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use risingwave_common_proc_macro::serde_prefix_all;
16use serde::de::Error as _;
17
18use super::*;
19
20#[derive(Copy, Clone, Debug, Default, ValueEnum, Serialize, Deserialize)]
21pub enum MetaBackend {
22    #[default]
23    Mem,
24    Sql, // any database url
25    Sqlite,
26    Postgres,
27    Mysql,
28}
29
30/// Compression algorithm for hummock version checkpoint serialization.
31#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
32#[serde(rename_all = "lowercase")]
33#[repr(i32)]
34pub enum CheckpointCompression {
35    /// No compression.
36    ///
37    /// NOTE: The numeric values are aligned with protobuf `CheckpointCompressionAlgorithm`.
38    None = 0,
39    /// Zstd compression (default, good balance between ratio and speed).
40    #[default]
41    Zstd = 1,
42    /// Lz4 compression (faster but lower ratio).
43    Lz4 = 2,
44}
45
46#[cfg(test)]
47mod tests {
48    use risingwave_pb::hummock::CheckpointCompressionAlgorithm;
49
50    use super::CheckpointCompression;
51
52    #[test]
53    fn checkpoint_compression_numeric_values_align_with_pb() {
54        assert_eq!(
55            CheckpointCompression::None as i32,
56            CheckpointCompressionAlgorithm::CheckpointCompressionUnspecified as i32
57        );
58        assert_eq!(
59            CheckpointCompression::Zstd as i32,
60            CheckpointCompressionAlgorithm::CheckpointCompressionZstd as i32
61        );
62        assert_eq!(
63            CheckpointCompression::Lz4 as i32,
64            CheckpointCompressionAlgorithm::CheckpointCompressionLz4 as i32
65        );
66    }
67}
68
69#[derive(Copy, Clone, Debug, Default)]
70pub enum DefaultParallelism {
71    #[default]
72    Full,
73    Default(NonZeroUsize),
74}
75
76impl Serialize for DefaultParallelism {
77    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
78    where
79        S: Serializer,
80    {
81        #[derive(Debug, Serialize, Deserialize)]
82        #[serde(untagged)]
83        enum Parallelism {
84            Str(String),
85            Int(usize),
86        }
87        match self {
88            DefaultParallelism::Full => Parallelism::Str("Full".to_owned()).serialize(serializer),
89            DefaultParallelism::Default(val) => {
90                Parallelism::Int(val.get() as _).serialize(serializer)
91            }
92        }
93    }
94}
95
96impl<'de> Deserialize<'de> for DefaultParallelism {
97    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
98    where
99        D: serde::Deserializer<'de>,
100    {
101        #[derive(Debug, Deserialize)]
102        #[serde(untagged)]
103        enum Parallelism {
104            Str(String),
105            Int(usize),
106        }
107        let p = Parallelism::deserialize(deserializer)?;
108        match p {
109            Parallelism::Str(s) => {
110                if s.trim().eq_ignore_ascii_case("full") {
111                    Ok(DefaultParallelism::Full)
112                } else {
113                    Err(serde::de::Error::custom(format!(
114                        "invalid default parallelism: {}",
115                        s
116                    )))
117                }
118            }
119            Parallelism::Int(i) => Ok(DefaultParallelism::Default(
120                // Note: we won't check whether this exceeds the maximum parallelism (i.e., vnode count)
121                // here because it requires extra context. The check will be done when scheduling jobs.
122                NonZeroUsize::new(i).ok_or_else(|| {
123                    serde::de::Error::custom("default parallelism should not be 0")
124                })?,
125            )),
126        }
127    }
128}
129
130/// The section `[meta]` in `risingwave.toml`.
131#[serde_with::apply(Option => #[serde(with = "none_as_empty_string")])]
132#[derive(Clone, Debug, Serialize, Deserialize, DefaultFromSerde, ConfigDoc)]
133pub struct MetaConfig {
134    /// Objects within `min_sst_retention_time_sec` won't be deleted by hummock full GC, even they
135    /// are dangling.
136    #[serde(default = "default::meta::min_sst_retention_time_sec")]
137    pub min_sst_retention_time_sec: u64,
138
139    /// Interval of automatic hummock full GC.
140    #[serde(default = "default::meta::full_gc_interval_sec")]
141    pub full_gc_interval_sec: u64,
142
143    /// Max number of object per full GC job can fetch.
144    #[serde(default = "default::meta::full_gc_object_limit")]
145    pub full_gc_object_limit: u64,
146
147    /// Duration in seconds to retain garbage collection history data.
148    #[serde(default = "default::meta::gc_history_retention_time_sec")]
149    pub gc_history_retention_time_sec: u64,
150
151    /// Max number of inflight time travel query.
152    #[serde(default = "default::meta::max_inflight_time_travel_query")]
153    pub max_inflight_time_travel_query: u64,
154
155    /// Schedule `Dynamic` compaction for all compaction groups with this interval.
156    /// Groups in cooldown (recently found to have no compaction work) are skipped.
157    #[serde(default = "default::meta::periodic_compaction_interval_sec")]
158    pub periodic_compaction_interval_sec: u64,
159
160    /// Interval of invoking a vacuum job, to remove stale metadata from meta store and objects
161    /// from object store.
162    #[serde(default = "default::meta::vacuum_interval_sec")]
163    pub vacuum_interval_sec: u64,
164
165    /// The spin interval inside a vacuum job. It avoids the vacuum job monopolizing resources of
166    /// meta node.
167    #[serde(default = "default::meta::vacuum_spin_interval_ms")]
168    pub vacuum_spin_interval_ms: u64,
169
170    /// Interval of invoking iceberg garbage collection, to expire old snapshots.
171    #[serde(default = "default::meta::iceberg_gc_interval_sec")]
172    pub iceberg_gc_interval_sec: u64,
173
174    /// Interval of scanning Iceberg table locations for orphan files.
175    #[serde(default = "default::meta::iceberg_orphan_file_cleanup_interval_sec")]
176    pub iceberg_orphan_file_cleanup_interval_sec: u64,
177
178    /// Maximum time to wait for an iceberg compaction task report before the lease expires.
179    #[serde(default = "default::meta::iceberg_compaction_report_timeout_sec")]
180    pub iceberg_compaction_report_timeout_sec: u64,
181
182    /// Maximum time to reuse cached iceberg compaction schedule config before refreshing it from
183    /// meta catalog.
184    #[serde(default = "default::meta::iceberg_compaction_config_refresh_interval_sec")]
185    pub iceberg_compaction_config_refresh_interval_sec: u64,
186
187    /// Whether to schedule one compaction for every Iceberg sink with automatic compaction when
188    /// meta starts. Compaction schedules are kept only in meta memory and are otherwise created by
189    /// sink commits, so without it, a sink that receives no commit after a restart is not
190    /// compacted, and a copy-on-write sink leaves its latest commits unpublished on `main`.
191    #[serde(default)]
192    pub iceberg_compaction_schedule_on_startup: bool,
193
194    /// Interval of hummock version checkpoint.
195    #[serde(default = "default::meta::hummock_version_checkpoint_interval_sec")]
196    pub hummock_version_checkpoint_interval_sec: u64,
197
198    /// Compression algorithm for hummock version checkpoint.
199    #[serde(default)]
200    pub checkpoint_compression_algorithm: CheckpointCompression,
201
202    /// Chunk size in bytes for reading large checkpoints.
203    /// Large checkpoints are read in parallel chunks to avoid single-request timeout issues.
204    /// Default: 128MB
205    #[serde(default = "default::meta::checkpoint_read_chunk_size")]
206    pub checkpoint_read_chunk_size: usize,
207
208    /// Maximum number of concurrent chunk reads when reading large checkpoints.
209    /// Higher values may improve read throughput but increase memory usage.
210    /// Memory usage = `checkpoint_read_chunk_size` * `checkpoint_read_max_in_flight_chunks`
211    /// Default: 4
212    #[serde(default = "default::meta::checkpoint_read_max_in_flight_chunks")]
213    pub checkpoint_read_max_in_flight_chunks: usize,
214
215    /// If enabled, `SSTable` object file and version delta will be retained.
216    ///
217    /// `SSTable` object file need to be deleted via full GC.
218    ///
219    /// version delta need to be manually deleted.
220    #[serde(default = "default::meta::enable_hummock_data_archive")]
221    pub enable_hummock_data_archive: bool,
222
223    /// The interval at which a Hummock version snapshot is taken for time travel.
224    ///
225    /// Larger value indicates less storage overhead but worse query performance.
226    #[serde(default = "default::meta::hummock_time_travel_snapshot_interval")]
227    pub hummock_time_travel_snapshot_interval: u64,
228
229    /// The minimum delta log number a new checkpoint should compact, otherwise the checkpoint
230    /// attempt is rejected.
231    #[serde(default = "default::meta::min_delta_log_num_for_hummock_version_checkpoint")]
232    pub min_delta_log_num_for_hummock_version_checkpoint: u64,
233
234    /// Maximum allowed heartbeat interval in seconds.
235    #[serde(default = "default::meta::max_heartbeat_interval_sec")]
236    pub max_heartbeat_interval_secs: u32,
237
238    /// Whether to enable fail-on-recovery. Should only be used in e2e tests.
239    #[serde(default)]
240    pub disable_recovery: bool,
241
242    /// Whether to clean up all foreground creating streaming jobs during recovery.
243    ///
244    /// This preserves the legacy recovery behavior. When disabled, only creating jobs whose
245    /// creation progress cannot be recovered are cleaned up.
246    #[serde(default)]
247    pub clean_all_foreground_jobs_on_recovery: bool,
248
249    /// Whether meta should request pausing all data sources on the next bootstrap.
250    /// This allows us to pause the cluster on next bootstrap in an offline way.
251    /// It's important for standalone or single node deployments.
252    /// In those cases, meta node, frontend and compute may all be co-located.
253    /// If the compute node enters an inconsistent state, and continuously crashloops,
254    /// we may not be able to connect to the cluster to run `alter system set pause_on_next_bootstrap = true;`.
255    /// By providing it in the static config, we can have an offline way to trigger the pause on bootstrap.
256    #[serde(default = "default::meta::pause_on_next_bootstrap_offline")]
257    pub pause_on_next_bootstrap_offline: bool,
258
259    /// Whether to disable adaptive-scaling feature.
260    #[serde(default)]
261    pub disable_automatic_parallelism_control: bool,
262
263    /// The number of streaming jobs per scaling operation.
264    #[serde(default = "default::meta::parallelism_control_batch_size")]
265    pub parallelism_control_batch_size: usize,
266
267    /// The period of parallelism control trigger.
268    #[serde(default = "default::meta::parallelism_control_trigger_period_sec")]
269    pub parallelism_control_trigger_period_sec: u64,
270
271    /// The first delay of parallelism control.
272    #[serde(default = "default::meta::parallelism_control_trigger_first_delay_sec")]
273    pub parallelism_control_trigger_first_delay_sec: u64,
274
275    #[serde(default = "default::meta::meta_leader_lease_secs")]
276    pub meta_leader_lease_secs: u64,
277
278    /// After specified seconds of idle (no mview or flush), the process will be exited.
279    /// It is mainly useful for playgrounds.
280    #[serde(default)]
281    pub dangerous_max_idle_secs: Option<u64>,
282
283    /// The default global parallelism for all streaming jobs, if user doesn't specify the
284    /// parallelism, this value will be used. `FULL` means use all available parallelism units,
285    /// otherwise it's a number.
286    #[serde(default = "default::meta::default_parallelism")]
287    pub default_parallelism: DefaultParallelism,
288
289    /// Whether to enable deterministic compaction scheduling, which
290    /// will disable all auto scheduling of compaction tasks.
291    /// Should only be used in e2e tests.
292    #[serde(default)]
293    pub enable_compaction_deterministic: bool,
294
295    /// Enable sanity check when SSTs are committed.
296    #[serde(default)]
297    pub enable_committed_sst_sanity_check: bool,
298
299    #[serde(default = "default::meta::node_num_monitor_interval_sec")]
300    pub node_num_monitor_interval_sec: u64,
301
302    #[serde(default = "default::meta::backend")]
303    pub backend: MetaBackend,
304
305    /// Schedule `space_reclaim` compaction for all compaction groups with this interval.
306    #[serde(default = "default::meta::periodic_space_reclaim_compaction_interval_sec")]
307    pub periodic_space_reclaim_compaction_interval_sec: u64,
308
309    /// Schedule `ttl_reclaim` compaction for all compaction groups with this interval.
310    #[serde(default = "default::meta::periodic_ttl_reclaim_compaction_interval_sec")]
311    pub periodic_ttl_reclaim_compaction_interval_sec: u64,
312
313    #[serde(default = "default::meta::periodic_tombstone_reclaim_compaction_interval_sec")]
314    pub periodic_tombstone_reclaim_compaction_interval_sec: u64,
315
316    #[serde(default = "default::meta::move_table_size_limit")]
317    #[deprecated]
318    pub move_table_size_limit: u64,
319
320    #[serde(default = "default::meta::split_group_size_limit")]
321    #[deprecated]
322    pub split_group_size_limit: u64,
323
324    #[serde(default = "default::meta::cut_table_size_limit")]
325    #[deprecated]
326    pub cut_table_size_limit: u64,
327
328    #[serde(default, flatten)]
329    #[config_doc(omitted)]
330    pub unrecognized: Unrecognized<Self>,
331
332    /// Whether config object storage bucket lifecycle to purge stale data.
333    #[serde(default)]
334    pub do_not_config_object_storage_lifecycle: bool,
335
336    /// Count of partition in split group. Meta will assign this value to every new group when it splits from default-group by automatically.
337    /// Each partition contains aligned data of `vnode_count / partition_vnode_count` consecutive virtual-nodes of one state table.
338    #[serde(default = "default::meta::partition_vnode_count")]
339    pub partition_vnode_count: u32,
340
341    /// The threshold of write throughput to trigger a group split.
342    #[serde(
343        default = "default::meta::table_high_write_throughput_threshold",
344        alias = "table_write_throughput_threshold"
345    )]
346    pub table_high_write_throughput_threshold: u64,
347
348    #[serde(
349        default = "default::meta::table_low_write_throughput_threshold",
350        alias = "min_table_split_write_throughput"
351    )]
352    /// The threshold of write throughput to trigger a group merge.
353    pub table_low_write_throughput_threshold: u64,
354
355    // If the compaction task does not report heartbeat beyond the
356    // `compaction_task_max_heartbeat_interval_secs` interval, we will cancel the task
357    #[serde(default = "default::meta::compaction_task_max_heartbeat_interval_secs")]
358    pub compaction_task_max_heartbeat_interval_secs: u64,
359
360    // If the compaction task does not change in progress beyond the
361    // `compaction_task_max_heartbeat_interval_secs` interval, we will cancel the task
362    #[serde(default = "default::meta::compaction_task_max_progress_interval_secs")]
363    pub compaction_task_max_progress_interval_secs: u64,
364
365    /// The number of compaction task ids to prefetch from the meta store in one batch.
366    #[serde(default = "default::meta::compaction_task_id_refill_capacity")]
367    pub compaction_task_id_refill_capacity: u32,
368
369    #[serde(default)]
370    #[config_doc(nested)]
371    pub compaction_config: CompactionConfig,
372
373    /// Count of partitions of tables in default group and materialized view group.
374    /// The meta node will decide according to some strategy whether to cut the boundaries of the file according to the vnode alignment.
375    /// Each partition contains aligned data of `vnode_count / hybrid_partition_vnode_count` consecutive virtual-nodes of one state table.
376    /// Set it zero to disable this feature.
377    #[serde(default = "default::meta::hybrid_partition_vnode_count")]
378    pub hybrid_partition_vnode_count: u32,
379
380    #[serde(default = "default::meta::event_log_enabled")]
381    pub event_log_enabled: bool,
382    /// Keeps the latest N events per channel.
383    #[serde(default = "default::meta::event_log_channel_max_size")]
384    pub event_log_channel_max_size: u32,
385
386    #[serde(default)]
387    #[config_doc(nested)]
388    pub developer: MetaDeveloperConfig,
389
390    /// Whether compactor should rewrite row to remove dropped column.
391    #[serde(default = "default::meta::enable_dropped_column_reclaim")]
392    pub enable_dropped_column_reclaim: bool,
393
394    /// Whether to split the compaction group when the size of the group exceeds the `compaction_group_config.max_estimated_group_size() * split_group_size_ratio`.
395    #[serde(default = "default::meta::split_group_size_ratio")]
396    pub split_group_size_ratio: f64,
397
398    /// Deprecated. Split now compares observed bytes per second directly with the high threshold.
399    #[serde(default = "default::meta::table_stat_high_write_throughput_ratio_for_split")]
400    #[deprecated]
401    pub table_stat_high_write_throughput_ratio_for_split: f64,
402
403    /// Deprecated. Merge now requires a full observed window with a low peak throughput.
404    #[serde(default = "default::meta::table_stat_low_write_throughput_ratio_for_merge")]
405    #[deprecated]
406    pub table_stat_low_write_throughput_ratio_for_merge: f64,
407
408    /// Deprecated and ignored. Use `table_write_throughput_retention_seconds`.
409    #[serde(default = "default::meta::table_stat_throuput_window_seconds_for_split")]
410    #[deprecated]
411    pub table_stat_throuput_window_seconds_for_split: usize,
412
413    /// Deprecated and ignored. Use `table_write_throughput_retention_seconds`.
414    #[serde(default = "default::meta::table_stat_throuput_window_seconds_for_merge")]
415    #[deprecated]
416    pub table_stat_throuput_window_seconds_for_merge: usize,
417
418    /// Retention in seconds for successful commit throughput observations. Split uses the
419    /// latest observed rate; merge requires a full observed retention with a low peak.
420    /// Six buckets may retain a boundary sample for up to one extra bucket
421    /// (one fifth of retention, at least one second). Zero retention is treated as one second.
422    #[serde(default = "default::meta::table_write_throughput_retention_seconds")]
423    pub table_write_throughput_retention_seconds: usize,
424
425    /// The threshold of table size in one compact task to decide whether to partition one table into `hybrid_partition_vnode_count` parts, which belongs to default group and materialized view group.
426    /// Set it max value of 64-bit number to disable this feature.
427    #[serde(default = "default::meta::compact_task_table_size_partition_threshold_low")]
428    pub compact_task_table_size_partition_threshold_low: u64,
429
430    /// The threshold of table size in one compact task to decide whether to partition one table into `partition_vnode_count` parts, which belongs to default group and materialized view group.
431    /// Set it max value of 64-bit number to disable this feature.
432    #[serde(default = "default::meta::compact_task_table_size_partition_threshold_high")]
433    pub compact_task_table_size_partition_threshold_high: u64,
434
435    /// The interval of the regular periodic compaction group split job.
436    /// This does not disable merge-triggered normalize splits when
437    /// `enable_compaction_group_normalize` is enabled.
438    #[serde(
439        default = "default::meta::periodic_scheduling_compaction_group_split_interval_sec",
440        alias = "periodic_split_compact_group_interval_sec"
441    )]
442    pub periodic_scheduling_compaction_group_split_interval_sec: u64,
443
444    /// Whether to normalize overlapping compaction groups before the regular merge scheduling.
445    #[serde(default = "default::meta::enable_compaction_group_normalize")]
446    pub enable_compaction_group_normalize: bool,
447
448    /// The maximum number of normalize splits in one scheduler round. Must be greater than 0.
449    #[serde(
450        default = "default::meta::max_normalize_splits_per_round",
451        deserialize_with = "deserialize_max_normalize_splits_per_round"
452    )]
453    pub max_normalize_splits_per_round: u64,
454
455    /// The interval of the periodic scheduling compaction group merge job.
456    #[serde(default = "default::meta::periodic_scheduling_compaction_group_merge_interval_sec")]
457    pub periodic_scheduling_compaction_group_merge_interval_sec: u64,
458
459    /// The threshold of each dimension of the compaction group after merging. When the dimension * `compaction_group_merge_dimension_threshold` >= limit, the merging job will be rejected.
460    #[serde(default = "default::meta::compaction_group_merge_dimension_threshold")]
461    pub compaction_group_merge_dimension_threshold: f64,
462
463    /// The interval that the CDC table splits initialization should yield to avoid overloading upstream system.
464    #[serde(default = "default::meta::cdc_table_split_init_sleep_interval_splits")]
465    pub cdc_table_split_init_sleep_interval_splits: u64,
466
467    /// The duration that the CDC table splits initialization should yield to avoid overloading upstream system.
468    #[serde(default = "default::meta::cdc_table_split_init_sleep_duration_millis")]
469    pub cdc_table_split_init_sleep_duration_millis: u64,
470
471    /// The batch size that the CDC table splits initialization should use when persisting to meta store.
472    #[serde(default = "default::meta::cdc_table_split_init_insert_batch_size")]
473    pub cdc_table_split_init_insert_batch_size: u64,
474
475    /// Whether to automatically migrate legacy table fragments when meta starts.
476    #[serde(default = "default::meta::enable_legacy_table_migration")]
477    pub enable_legacy_table_migration: bool,
478
479    #[serde(default)]
480    #[config_doc(nested)]
481    pub meta_store_config: MetaStoreConfig,
482}
483
484/// Note: only applies to meta store backends other than `SQLite`.
485#[serde_with::apply(Option => #[serde(with = "none_as_empty_string")])]
486#[derive(Clone, Debug, Serialize, Deserialize, DefaultFromSerde, ConfigDoc)]
487pub struct MetaStoreConfig {
488    /// Maximum number of connections for the meta store connection pool.
489    #[serde(default = "default::meta_store_config::max_connections")]
490    pub max_connections: u32,
491    /// Minimum number of connections for the meta store connection pool.
492    #[serde(default = "default::meta_store_config::min_connections")]
493    pub min_connections: u32,
494    /// Connection timeout in seconds for a meta store connection.
495    #[serde(default = "default::meta_store_config::connection_timeout_sec")]
496    pub connection_timeout_sec: u64,
497    /// Idle timeout in seconds for a meta store connection.
498    #[serde(default = "default::meta_store_config::idle_timeout_sec")]
499    pub idle_timeout_sec: u64,
500    /// Acquire timeout in seconds for a meta store connection.
501    #[serde(default = "default::meta_store_config::acquire_timeout_sec")]
502    pub acquire_timeout_sec: u64,
503}
504
505fn deserialize_max_normalize_splits_per_round<'de, D>(deserializer: D) -> Result<u64, D::Error>
506where
507    D: serde::Deserializer<'de>,
508{
509    let value = u64::deserialize(deserializer)?;
510    if value == 0 {
511        return Err(D::Error::custom(
512            "meta.max_normalize_splits_per_round must be greater than 0",
513        ));
514    }
515    Ok(value)
516}
517
518/// The subsections `[meta.developer]`.
519///
520/// It is put at [`MetaConfig::developer`].
521#[serde_prefix_all("meta_", mode = "alias")]
522#[serde_with::apply(Option => #[serde(with = "none_as_empty_string")])]
523#[derive(Clone, Debug, Serialize, Deserialize, DefaultFromSerde, ConfigDoc)]
524pub struct MetaDeveloperConfig {
525    /// The number of traces to be cached in-memory by the tracing collector
526    /// embedded in the meta node.
527    #[serde(default = "default::developer::meta_cached_traces_num")]
528    pub cached_traces_num: u32,
529
530    /// The maximum memory usage in bytes for the tracing collector embedded
531    /// in the meta node.
532    #[serde(default = "default::developer::meta_cached_traces_memory_limit_bytes")]
533    pub cached_traces_memory_limit_bytes: usize,
534
535    /// Compaction picker config
536    #[serde(default = "default::developer::enable_trivial_move")]
537    pub enable_trivial_move: bool,
538    #[serde(default = "default::developer::enable_check_task_level_overlap")]
539    pub enable_check_task_level_overlap: bool,
540    #[serde(default = "default::developer::max_trivial_move_task_count_per_loop")]
541    pub max_trivial_move_task_count_per_loop: usize,
542
543    #[serde(default = "default::developer::max_get_task_probe_times")]
544    pub max_get_task_probe_times: usize,
545
546    /// Max number of actor allowed per parallelism (default = 100).
547    /// CREATE MV/Table will be noticed when the number of actors exceeds this limit.
548    #[serde(default = "default::developer::actor_cnt_per_worker_parallelism_soft_limit")]
549    pub actor_cnt_per_worker_parallelism_soft_limit: usize,
550
551    /// Max number of actor allowed per parallelism (default = 400).
552    /// CREATE MV/Table will be rejected when the number of actors exceeds this limit.
553    #[serde(default = "default::developer::actor_cnt_per_worker_parallelism_hard_limit")]
554    pub actor_cnt_per_worker_parallelism_hard_limit: usize,
555
556    /// Max number of SSTs fetched from meta store per SELECT, during time travel Hummock version replay.
557    #[serde(default = "default::developer::hummock_time_travel_sst_info_fetch_batch_size")]
558    pub hummock_time_travel_sst_info_fetch_batch_size: usize,
559
560    /// Max number of SSTs inserted into meta store per INSERT, during time travel metadata writing.
561    #[serde(default = "default::developer::hummock_time_travel_sst_info_insert_batch_size")]
562    pub hummock_time_travel_sst_info_insert_batch_size: usize,
563
564    #[serde(default = "default::developer::time_travel_vacuum_interval_sec")]
565    pub time_travel_vacuum_interval_sec: u64,
566
567    #[serde(default = "default::developer::time_travel_vacuum_max_version_count")]
568    pub time_travel_vacuum_max_version_count: Option<u32>,
569
570    /// Max number of epoch-to-version inserted into meta store per INSERT, during time travel metadata writing.
571    #[serde(default = "default::developer::hummock_time_travel_epoch_version_insert_batch_size")]
572    pub hummock_time_travel_epoch_version_insert_batch_size: usize,
573
574    /// Max number of version deltas fetched from meta store per SELECT, during time travel metadata vacuum.
575    #[serde(default = "default::developer::hummock_time_travel_delta_fetch_batch_size")]
576    pub hummock_time_travel_delta_fetch_batch_size: usize,
577
578    #[serde(default = "default::developer::hummock_gc_history_insert_batch_size")]
579    pub hummock_gc_history_insert_batch_size: usize,
580
581    #[serde(default = "default::developer::hummock_time_travel_filter_out_objects_batch_size")]
582    pub hummock_time_travel_filter_out_objects_batch_size: usize,
583
584    #[serde(default = "default::developer::hummock_time_travel_filter_out_objects_v1")]
585    pub hummock_time_travel_filter_out_objects_v1: bool,
586
587    #[serde(
588        default = "default::developer::hummock_time_travel_filter_out_objects_list_version_batch_size"
589    )]
590    pub hummock_time_travel_filter_out_objects_list_version_batch_size: usize,
591
592    #[serde(
593        default = "default::developer::hummock_time_travel_filter_out_objects_list_delta_batch_size"
594    )]
595    pub hummock_time_travel_filter_out_objects_list_delta_batch_size: usize,
596
597    #[serde(default)]
598    pub compute_client_config: RpcClientConfig,
599
600    #[serde(default)]
601    pub stream_client_config: RpcClientConfig,
602
603    #[serde(default)]
604    pub frontend_client_config: RpcClientConfig,
605
606    #[serde(default = "default::developer::table_change_log_insert_batch_size")]
607    pub table_change_log_insert_batch_size: u64,
608
609    #[serde(default = "default::developer::table_change_log_delete_batch_size")]
610    pub table_change_log_delete_batch_size: u64,
611
612    #[serde(default = "default::developer::table_change_log_truncate_interval_sec")]
613    pub table_change_log_truncate_interval_sec: u64,
614}
615
616#[serde_with::apply(Option => #[serde(with = "none_as_empty_string")])]
617#[derive(Clone, Debug, Serialize, Deserialize, DefaultFromSerde, ConfigDoc)]
618pub struct CompactionConfig {
619    #[serde(default = "default::compaction_config::max_bytes_for_level_base")]
620    pub max_bytes_for_level_base: u64,
621    #[serde(default = "default::compaction_config::max_bytes_for_level_multiplier")]
622    pub max_bytes_for_level_multiplier: u64,
623    #[serde(default = "default::compaction_config::max_compaction_bytes")]
624    pub max_compaction_bytes: u64,
625    #[serde(default = "default::compaction_config::sub_level_max_compaction_bytes")]
626    pub sub_level_max_compaction_bytes: u64,
627    #[serde(default = "default::compaction_config::level0_tier_compact_file_number")]
628    pub level0_tier_compact_file_number: u64,
629    #[serde(default = "default::compaction_config::target_file_size_base")]
630    pub target_file_size_base: u64,
631    #[serde(default = "default::compaction_config::compaction_filter_mask")]
632    pub compaction_filter_mask: u32,
633    #[serde(default = "default::compaction_config::max_sub_compaction")]
634    pub max_sub_compaction: u32,
635    #[serde(default = "default::compaction_config::level0_stop_write_threshold_sub_level_number")]
636    pub level0_stop_write_threshold_sub_level_number: u64,
637    #[serde(default = "default::compaction_config::level0_sub_level_compact_level_count")]
638    pub level0_sub_level_compact_level_count: u32,
639    #[serde(
640        default = "default::compaction_config::level0_overlapping_sub_level_compact_level_count"
641    )]
642    pub level0_overlapping_sub_level_compact_level_count: u32,
643    #[serde(default = "default::compaction_config::max_space_reclaim_bytes")]
644    pub max_space_reclaim_bytes: u64,
645    #[serde(default = "default::compaction_config::level0_max_compact_file_number")]
646    pub level0_max_compact_file_number: u64,
647    #[serde(default = "default::compaction_config::tombstone_reclaim_ratio")]
648    pub tombstone_reclaim_ratio: u32,
649    #[serde(default = "default::compaction_config::enable_emergency_picker")]
650    pub enable_emergency_picker: bool,
651    #[serde(default = "default::compaction_config::max_level")]
652    pub max_level: u32,
653    #[serde(default = "default::compaction_config::sst_allowed_trivial_move_min_size")]
654    pub sst_allowed_trivial_move_min_size: u64,
655    #[serde(default = "default::compaction_config::sst_allowed_trivial_move_max_count")]
656    pub sst_allowed_trivial_move_max_count: u32,
657    #[serde(default = "default::compaction_config::max_l0_compact_level_count")]
658    pub max_l0_compact_level_count: u32,
659    #[serde(default = "default::compaction_config::disable_auto_group_scheduling")]
660    pub disable_auto_group_scheduling: bool,
661    #[serde(default = "default::compaction_config::max_overlapping_level_size")]
662    pub max_overlapping_level_size: u64,
663    #[serde(default = "default::compaction_config::emergency_level0_sst_file_count")]
664    pub emergency_level0_sst_file_count: u32,
665    #[serde(default = "default::compaction_config::emergency_level0_sub_level_partition")]
666    pub emergency_level0_sub_level_partition: u32,
667    #[serde(default = "default::compaction_config::level0_stop_write_threshold_max_sst_count")]
668    pub level0_stop_write_threshold_max_sst_count: u32,
669    #[serde(default = "default::compaction_config::level0_stop_write_threshold_max_size")]
670    pub level0_stop_write_threshold_max_size: u64,
671    #[serde(default = "default::compaction_config::enable_optimize_l0_interval_selection")]
672    pub enable_optimize_l0_interval_selection: bool,
673    /// KV-count threshold for using blocked xor filters when output filter layout is "auto".
674    ///
675    /// When `sstable_filter_layout[level]` is "auto", compaction will build blocked xor filters if
676    /// the estimated key count of one output SST exceeds this threshold. Otherwise it will build a
677    /// single non-blocked xor filter for that output.
678    ///
679    /// This is an output-SST-level heuristic. Older versions compared the threshold with the total
680    /// key count of the whole compaction task, which could classify many small output SSTs as
681    /// blocked only because they came from a large task. With the current heuristic, those outputs
682    /// can be classified back to plain filters.
683    ///
684    /// Note: shared-buffer flush does not read compaction group config, and always uses the
685    /// built-in default threshold.
686    #[serde(default = "default::compaction_config::blocked_xor_filter_kv_count_threshold")]
687    #[serde(alias = "max_kv_count_for_xor16")]
688    pub blocked_xor_filter_kv_count_threshold: Option<u64>,
689    #[serde(default = "default::compaction_config::max_vnode_key_range_bytes")]
690    pub max_vnode_key_range_bytes: Option<u64>,
691    /// Per-level SST filter type for compaction output. Supported values: "none", "xor16", "xor8".
692    ///
693    /// Index by LSM level: `0..=max_level`. Note: L0 (index 0) is currently ignored by shared-buffer
694    /// flush, which always uses "xor16".
695    #[serde(default = "default::compaction_config::sstable_filter_type")]
696    pub sstable_filter_type: Vec<String>,
697    /// Per-level xor filter layout for compaction output.
698    ///
699    /// `auto` uses the kv-count heuristic; `plain` forces non-blocked filters; `blocked`
700    /// forces block-based filters. Explicit `plain` and `blocked` values ignore the kv-count
701    /// threshold. This setting is ignored when the corresponding `sstable_filter_type` is "none".
702    ///
703    /// Index by LSM level: `0..=max_level`. Note: L0 (index 0) is currently ignored by shared-buffer
704    /// flush, which always uses "auto".
705    #[serde(default = "default::compaction_config::sstable_filter_layout")]
706    pub sstable_filter_layout: Vec<String>,
707}
708
709pub mod default {
710    pub use crate::config::default::developer;
711
712    pub mod meta {
713        use crate::config::{DefaultParallelism, MetaBackend};
714
715        pub fn min_sst_retention_time_sec() -> u64 {
716            3600 * 6
717        }
718
719        pub fn gc_history_retention_time_sec() -> u64 {
720            3600 * 6
721        }
722
723        pub fn full_gc_interval_sec() -> u64 {
724            3600
725        }
726
727        pub fn full_gc_object_limit() -> u64 {
728            100_000
729        }
730
731        pub fn max_inflight_time_travel_query() -> u64 {
732            1000
733        }
734
735        pub fn periodic_compaction_interval_sec() -> u64 {
736            300
737        }
738
739        pub fn vacuum_interval_sec() -> u64 {
740            30
741        }
742
743        pub fn vacuum_spin_interval_ms() -> u64 {
744            100
745        }
746
747        pub fn iceberg_gc_interval_sec() -> u64 {
748            3600
749        }
750
751        pub fn iceberg_orphan_file_cleanup_interval_sec() -> u64 {
752            7 * 24 * 60 * 60
753        }
754
755        pub fn iceberg_compaction_report_timeout_sec() -> u64 {
756            30 * 60
757        }
758
759        pub fn iceberg_compaction_config_refresh_interval_sec() -> u64 {
760            60
761        }
762
763        pub fn hummock_version_checkpoint_interval_sec() -> u64 {
764            30
765        }
766
767        pub fn checkpoint_read_chunk_size() -> usize {
768            128 * 1024 * 1024 // 128MB
769        }
770
771        pub fn checkpoint_read_max_in_flight_chunks() -> usize {
772            4
773        }
774
775        pub fn enable_hummock_data_archive() -> bool {
776            false
777        }
778
779        pub fn hummock_time_travel_snapshot_interval() -> u64 {
780            100
781        }
782
783        pub fn min_delta_log_num_for_hummock_version_checkpoint() -> u64 {
784            10
785        }
786
787        pub fn max_heartbeat_interval_sec() -> u32 {
788            60
789        }
790
791        pub fn meta_leader_lease_secs() -> u64 {
792            30
793        }
794
795        pub fn default_parallelism() -> DefaultParallelism {
796            DefaultParallelism::Full
797        }
798
799        pub fn pause_on_next_bootstrap_offline() -> bool {
800            false
801        }
802
803        pub fn node_num_monitor_interval_sec() -> u64 {
804            10
805        }
806
807        pub fn backend() -> MetaBackend {
808            MetaBackend::Mem
809        }
810
811        pub fn periodic_space_reclaim_compaction_interval_sec() -> u64 {
812            3600 // 60min
813        }
814
815        pub fn periodic_ttl_reclaim_compaction_interval_sec() -> u64 {
816            1800 // 30mi
817        }
818
819        pub fn periodic_scheduling_compaction_group_split_interval_sec() -> u64 {
820            10 // 10s
821        }
822
823        pub fn periodic_tombstone_reclaim_compaction_interval_sec() -> u64 {
824            600
825        }
826
827        // limit the size of state table to trigger split by high throughput
828        pub fn move_table_size_limit() -> u64 {
829            10 * 1024 * 1024 * 1024 // 10GB
830        }
831
832        // limit the size of group to trigger split by group_size and avoid too many small groups
833        pub fn split_group_size_limit() -> u64 {
834            64 * 1024 * 1024 * 1024 // 64GB
835        }
836
837        pub fn partition_vnode_count() -> u32 {
838            16
839        }
840
841        pub fn table_high_write_throughput_threshold() -> u64 {
842            16 * 1024 * 1024 // 16MB
843        }
844
845        pub fn table_low_write_throughput_threshold() -> u64 {
846            4 * 1024 * 1024 // 4MB
847        }
848
849        pub fn compaction_task_max_heartbeat_interval_secs() -> u64 {
850            30 // 30s
851        }
852
853        pub fn compaction_task_max_progress_interval_secs() -> u64 {
854            60 * 10 // 10min
855        }
856
857        pub fn compaction_task_id_refill_capacity() -> u32 {
858            64
859        }
860
861        pub fn cut_table_size_limit() -> u64 {
862            1024 * 1024 * 1024 // 1GB
863        }
864
865        pub fn hybrid_partition_vnode_count() -> u32 {
866            4
867        }
868
869        pub fn compact_task_table_size_partition_threshold_low() -> u64 {
870            128 * 1024 * 1024 // 128MB
871        }
872
873        pub fn compact_task_table_size_partition_threshold_high() -> u64 {
874            512 * 1024 * 1024 // 512MB
875        }
876
877        pub fn event_log_enabled() -> bool {
878            true
879        }
880
881        pub fn event_log_channel_max_size() -> u32 {
882            10
883        }
884
885        pub fn parallelism_control_batch_size() -> usize {
886            10
887        }
888
889        pub fn parallelism_control_trigger_period_sec() -> u64 {
890            10
891        }
892
893        pub fn parallelism_control_trigger_first_delay_sec() -> u64 {
894            30
895        }
896
897        pub fn enable_dropped_column_reclaim() -> bool {
898            false
899        }
900
901        pub fn split_group_size_ratio() -> f64 {
902            0.9
903        }
904
905        pub fn table_stat_high_write_throughput_ratio_for_split() -> f64 {
906            0.5
907        }
908
909        pub fn table_stat_low_write_throughput_ratio_for_merge() -> f64 {
910            0.7
911        }
912
913        pub fn table_stat_throuput_window_seconds_for_split() -> usize {
914            60
915        }
916
917        pub fn table_stat_throuput_window_seconds_for_merge() -> usize {
918            240
919        }
920
921        pub fn table_write_throughput_retention_seconds() -> usize {
922            300
923        }
924
925        pub fn periodic_scheduling_compaction_group_merge_interval_sec() -> u64 {
926            60 * 10 // 10min
927        }
928
929        pub fn enable_compaction_group_normalize() -> bool {
930            true
931        }
932
933        pub fn max_normalize_splits_per_round() -> u64 {
934            4
935        }
936
937        pub fn compaction_group_merge_dimension_threshold() -> f64 {
938            1.2
939        }
940
941        pub fn cdc_table_split_init_sleep_interval_splits() -> u64 {
942            1000
943        }
944
945        pub fn cdc_table_split_init_sleep_duration_millis() -> u64 {
946            500
947        }
948
949        pub fn cdc_table_split_init_insert_batch_size() -> u64 {
950            100
951        }
952
953        pub fn enable_legacy_table_migration() -> bool {
954            true
955        }
956    }
957
958    pub mod meta_store_config {
959        const DEFAULT_MAX_CONNECTIONS: u32 = 10;
960        const DEFAULT_MIN_CONNECTIONS: u32 = 1;
961        const DEFAULT_CONNECTION_TIMEOUT_SEC: u64 = 10;
962        const DEFAULT_IDLE_TIMEOUT_SEC: u64 = 30;
963        const DEFAULT_ACQUIRE_TIMEOUT_SEC: u64 = 30;
964
965        pub fn max_connections() -> u32 {
966            DEFAULT_MAX_CONNECTIONS
967        }
968
969        pub fn min_connections() -> u32 {
970            DEFAULT_MIN_CONNECTIONS
971        }
972
973        pub fn connection_timeout_sec() -> u64 {
974            DEFAULT_CONNECTION_TIMEOUT_SEC
975        }
976
977        pub fn idle_timeout_sec() -> u64 {
978            DEFAULT_IDLE_TIMEOUT_SEC
979        }
980
981        pub fn acquire_timeout_sec() -> u64 {
982            DEFAULT_ACQUIRE_TIMEOUT_SEC
983        }
984    }
985
986    pub mod compaction_config {
987        const MB: u64 = 1024 * 1024;
988        const GB: u64 = 1024 * 1024 * 1024;
989        const DEFAULT_MAX_COMPACTION_BYTES: u64 = 2 * GB; // 2GB
990        const DEFAULT_MIN_COMPACTION_BYTES: u64 = 128 * MB; // 128MB
991        const DEFAULT_MAX_BYTES_FOR_LEVEL_BASE: u64 = 512 * MB; // 512MB
992
993        // decrease this configure when the generation of checkpoint barrier is not frequent.
994        const DEFAULT_TIER_COMPACT_TRIGGER_NUMBER: u64 = 12;
995        const DEFAULT_TARGET_FILE_SIZE_BASE: u64 = 32 * MB;
996        // 32MB
997        const DEFAULT_MAX_SUB_COMPACTION: u32 = 4;
998        const DEFAULT_LEVEL_MULTIPLIER: u64 = 10;
999        const DEFAULT_MAX_SPACE_RECLAIM_BYTES: u64 = 512 * MB; // 512MB;
1000        const DEFAULT_LEVEL0_STOP_WRITE_THRESHOLD_SUB_LEVEL_NUMBER: u64 = 128;
1001        const DEFAULT_MAX_COMPACTION_FILE_COUNT: u64 = 100;
1002        const DEFAULT_MIN_SUB_LEVEL_COMPACT_LEVEL_COUNT: u32 = 3;
1003        const DEFAULT_MIN_OVERLAPPING_SUB_LEVEL_COMPACT_LEVEL_COUNT: u32 = 12;
1004        const DEFAULT_TOMBSTONE_RATIO_PERCENT: u32 = 40;
1005        const DEFAULT_EMERGENCY_PICKER: bool = true;
1006        const DEFAULT_MAX_LEVEL: u32 = 6;
1007        const DEFAULT_MAX_L0_COMPACT_LEVEL_COUNT: u32 = 42;
1008        const DEFAULT_SST_ALLOWED_TRIVIAL_MOVE_MIN_SIZE: u64 = 4 * MB;
1009        const DEFAULT_SST_ALLOWED_TRIVIAL_MOVE_MAX_COUNT: u32 = 256;
1010        const DEFAULT_EMERGENCY_LEVEL0_SST_FILE_COUNT: u32 = 2000; // > 50G / 32M = 1600
1011        const DEFAULT_EMERGENCY_LEVEL0_SUB_LEVEL_PARTITION: u32 = 256;
1012        const DEFAULT_LEVEL0_STOP_WRITE_THRESHOLD_MAX_SST_COUNT: u32 = 5000;
1013        const DEFAULT_LEVEL0_STOP_WRITE_THRESHOLD_MAX_SIZE: u64 = 300 * 1024 * MB; // 300GB
1014        const DEFAULT_ENABLE_OPTIMIZE_L0_INTERVAL_SELECTION: bool = true;
1015        pub const DEFAULT_BLOCKED_XOR_FILTER_KV_COUNT_THRESHOLD: u64 = 256 * 1024;
1016        const DEFAULT_MAX_VNODE_KEY_RANGE_BYTES: Option<u64> = None;
1017
1018        use crate::catalog::hummock::CompactionFilterFlag;
1019
1020        pub fn max_bytes_for_level_base() -> u64 {
1021            DEFAULT_MAX_BYTES_FOR_LEVEL_BASE
1022        }
1023
1024        pub fn max_bytes_for_level_multiplier() -> u64 {
1025            DEFAULT_LEVEL_MULTIPLIER
1026        }
1027
1028        pub fn max_compaction_bytes() -> u64 {
1029            DEFAULT_MAX_COMPACTION_BYTES
1030        }
1031
1032        pub fn sub_level_max_compaction_bytes() -> u64 {
1033            DEFAULT_MIN_COMPACTION_BYTES
1034        }
1035
1036        pub fn level0_tier_compact_file_number() -> u64 {
1037            DEFAULT_TIER_COMPACT_TRIGGER_NUMBER
1038        }
1039
1040        pub fn target_file_size_base() -> u64 {
1041            DEFAULT_TARGET_FILE_SIZE_BASE
1042        }
1043
1044        pub fn compaction_filter_mask() -> u32 {
1045            (CompactionFilterFlag::STATE_CLEAN | CompactionFilterFlag::TTL).into()
1046        }
1047
1048        pub fn max_sub_compaction() -> u32 {
1049            DEFAULT_MAX_SUB_COMPACTION
1050        }
1051
1052        pub fn level0_stop_write_threshold_sub_level_number() -> u64 {
1053            DEFAULT_LEVEL0_STOP_WRITE_THRESHOLD_SUB_LEVEL_NUMBER
1054        }
1055
1056        pub fn level0_sub_level_compact_level_count() -> u32 {
1057            DEFAULT_MIN_SUB_LEVEL_COMPACT_LEVEL_COUNT
1058        }
1059
1060        pub fn level0_overlapping_sub_level_compact_level_count() -> u32 {
1061            DEFAULT_MIN_OVERLAPPING_SUB_LEVEL_COMPACT_LEVEL_COUNT
1062        }
1063
1064        pub fn max_space_reclaim_bytes() -> u64 {
1065            DEFAULT_MAX_SPACE_RECLAIM_BYTES
1066        }
1067
1068        pub fn level0_max_compact_file_number() -> u64 {
1069            DEFAULT_MAX_COMPACTION_FILE_COUNT
1070        }
1071
1072        pub fn tombstone_reclaim_ratio() -> u32 {
1073            DEFAULT_TOMBSTONE_RATIO_PERCENT
1074        }
1075
1076        pub fn enable_emergency_picker() -> bool {
1077            DEFAULT_EMERGENCY_PICKER
1078        }
1079
1080        pub fn max_level() -> u32 {
1081            DEFAULT_MAX_LEVEL
1082        }
1083
1084        pub fn max_l0_compact_level_count() -> u32 {
1085            DEFAULT_MAX_L0_COMPACT_LEVEL_COUNT
1086        }
1087
1088        pub fn sst_allowed_trivial_move_min_size() -> u64 {
1089            DEFAULT_SST_ALLOWED_TRIVIAL_MOVE_MIN_SIZE
1090        }
1091
1092        pub fn disable_auto_group_scheduling() -> bool {
1093            false
1094        }
1095
1096        pub fn max_overlapping_level_size() -> u64 {
1097            256 * MB
1098        }
1099
1100        pub fn sst_allowed_trivial_move_max_count() -> u32 {
1101            DEFAULT_SST_ALLOWED_TRIVIAL_MOVE_MAX_COUNT
1102        }
1103
1104        pub fn emergency_level0_sst_file_count() -> u32 {
1105            DEFAULT_EMERGENCY_LEVEL0_SST_FILE_COUNT
1106        }
1107
1108        pub fn emergency_level0_sub_level_partition() -> u32 {
1109            DEFAULT_EMERGENCY_LEVEL0_SUB_LEVEL_PARTITION
1110        }
1111
1112        pub fn level0_stop_write_threshold_max_sst_count() -> u32 {
1113            DEFAULT_LEVEL0_STOP_WRITE_THRESHOLD_MAX_SST_COUNT
1114        }
1115
1116        pub fn level0_stop_write_threshold_max_size() -> u64 {
1117            DEFAULT_LEVEL0_STOP_WRITE_THRESHOLD_MAX_SIZE
1118        }
1119
1120        pub fn enable_optimize_l0_interval_selection() -> bool {
1121            DEFAULT_ENABLE_OPTIMIZE_L0_INTERVAL_SELECTION
1122        }
1123
1124        pub fn blocked_xor_filter_kv_count_threshold() -> Option<u64> {
1125            Some(DEFAULT_BLOCKED_XOR_FILTER_KV_COUNT_THRESHOLD)
1126        }
1127
1128        /// Default compression algorithm for a given LSM-tree level.
1129        ///
1130        /// This is the single source of truth used by meta's default compaction config builder
1131        /// and by SQL `ALTER COMPACTION GROUP ... SET compression_algorithm = DEFAULT`.
1132        pub fn compression_algorithm_for_level(level: u32) -> &'static str {
1133            // L0/L1 and L2 do not use compression algorithms.
1134            // L3 - L4 use Lz4, else use Zstd.
1135            match level {
1136                0..=2 => "None",
1137                3 | 4 => "Lz4",
1138                _ => "Zstd",
1139            }
1140        }
1141
1142        /// Default compression algorithm vector for levels `0..=max_level`.
1143        pub fn compression_algorithm_vec(max_level: u32) -> Vec<String> {
1144            (0..=max_level)
1145                .map(|level| compression_algorithm_for_level(level).to_owned())
1146                .collect()
1147        }
1148
1149        pub fn max_vnode_key_range_bytes() -> Option<u64> {
1150            DEFAULT_MAX_VNODE_KEY_RANGE_BYTES
1151        }
1152
1153        pub fn sstable_filter_type() -> Vec<String> {
1154            vec![
1155                "xor16".to_owned(),
1156                "xor16".to_owned(),
1157                "xor16".to_owned(),
1158                "xor16".to_owned(),
1159                "xor16".to_owned(),
1160                "xor8".to_owned(),
1161                "xor8".to_owned(),
1162            ]
1163        }
1164
1165        pub fn sstable_filter_layout() -> Vec<String> {
1166            vec![
1167                "auto".to_owned(),
1168                "blocked".to_owned(),
1169                "blocked".to_owned(),
1170                "blocked".to_owned(),
1171                "blocked".to_owned(),
1172                "blocked".to_owned(),
1173                "blocked".to_owned(),
1174            ]
1175        }
1176    }
1177}