From fd7d53ba4198083749dafb852c33285a64db1270 Mon Sep 17 00:00:00 2001 From: dawn <90008@klbr.net> Date: Sun, 12 Jul 2026 22:01:10 +0300 Subject: [PATCH] [db] compress L0 for monotonic-key keyspaces monotonic {seq}/{id}/{time_us}|{id} keys make every l0 flush disjoint, so lsm-tree leveled compaction trivial-moves segments down without rewriting. the l0 compression+block-size slot is therefore permanent for relay_events, events, and jetstream_events -- with l0=none they were stored uncompressed forever and the l1+ zstd policy was dead code (prod relay: btrfs reclaiming 1.55x on 155/157g of raw relay_events). set l0 compression to zstd:3 and l0 block size to 128kib (matching btrfs's 128k compression window so ratio reaches parity) on the non-ephemeral paths. newest events are still served uncompressed from the memtable; only flushed historical segments (read on cursor replay) pay decompress. also give relay_events its own dict lookup key instead of borrowing the nonexistent 'events' key in relay mode. --- src/db/schema.rs | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/db/schema.rs b/src/db/schema.rs index eee48ae..9c385d0 100644 --- a/src/db/schema.rs +++ b/src/db/schema.rs @@ -522,9 +522,10 @@ impl Schema for Events { cx.cfg .ephemeral .then(|| BlockSizePolicy::new([kb(64), kb(128), kb(256)])) - .unwrap_or_else(|| BlockSizePolicy::new([kb(16), kb(64)])), + .unwrap_or_else(|| BlockSizePolicy::new([kb(128), kb(256)])), ) - // we are streaming the new events to consumers so we dont want to compress them + // monotonic {ID} keys are trivial-moved down (never rewritten), so the L0 + // policy is permanent; the live tail is served uncompressed from the memtable .data_block_compression_policy( cx.cfg .ephemeral @@ -536,7 +537,7 @@ impl Schema for Events { }) .unwrap_or_else(|| { CompressionPolicy::new([ - CompressionType::None, + (cx.compression)("events", 3), (cx.compression)("events", 3), (cx.compression)("events", 3), (cx.compression)("events", 5), @@ -583,9 +584,9 @@ impl Schema for JetstreamEvents { // time-ordered append-only stream metadata, only iterated for replay. .expect_point_read_hits(true) .max_memtable_size(mb(cx.cfg.db_events_memtable_size_mb)) - .data_block_size_policy(BlockSizePolicy::new([kb(16), kb(64), kb(128)])) + .data_block_size_policy(BlockSizePolicy::new([kb(128), kb(256)])) .data_block_compression_policy(CompressionPolicy::new([ - CompressionType::None, + (cx.compression)("jetstream_events", 3), (cx.compression)("jetstream_events", 3), (cx.compression)("jetstream_events", 5), ])) @@ -615,12 +616,14 @@ impl Schema for RelayEvents { // only iterated for cursor replay .expect_point_read_hits(true) .max_memtable_size(mb(cx.cfg.db_events_memtable_size_mb)) - .data_block_size_policy(BlockSizePolicy::new([kb(64), kb(128), kb(256)])) + .data_block_size_policy(BlockSizePolicy::new([kb(128), kb(256)])) + // monotonic {SEQ} keys are trivial-moved down (never rewritten), so L0 + // compression is permanent; the live tail is served from the memtable .data_block_compression_policy(CompressionPolicy::new([ - CompressionType::None, - (cx.compression)("events", 3), - (cx.compression)("events", 3), - (cx.compression)("events", 5), + (cx.compression)("relay_events", 3), + (cx.compression)("relay_events", 3), + (cx.compression)("relay_events", 3), + (cx.compression)("relay_events", 5), ])) .data_block_restart_interval_policy(RestartIntervalPolicy::new([64, 128])) } -- 2.51.2