Skip to content

Commit cd4fc90

Browse files
authored
Merge pull request #485 from tidesdb/latest-minors-5
align kafka and admintool references with latest versions
2 parents 8259c3c + dc5c7bd commit cd4fc90

2 files changed

Lines changed: 142 additions & 4 deletions

File tree

src/content/docs/reference/admintool.md

Lines changed: 98 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,25 @@ open <path> [options]
6565
|--------|-------------|
6666
| `--unified` | Enable unified memtable mode |
6767
| `--unified-buffer-size <n>` | Unified memtable write buffer size (bytes) |
68+
| `--unified-skip-list-max-level <n>` | Skip list max level for unified memtable (0 = default 12) |
69+
| `--unified-skip-list-probability <f>` | Skip list probability for unified memtable (0 = default 0.25) |
6870
| `--unified-sync <mode>` | Unified WAL sync mode (`none`\|`interval`\|`full`) |
6971
| `--unified-sync-interval <us>` | Unified WAL sync interval (microseconds) |
7072
| `--cache-size <n>` | Block cache size (bytes, 0 to disable) |
7173
| `--max-open-sstables <n>` | Max cached SSTable structures |
7274
| `--flush-threads <n>` | Flush thread pool size |
7375
| `--compaction-threads <n>` | Compaction thread pool size |
76+
| `--max-concurrent-flushes <n>` | Global cap on in-flight memtable flushes across all CFs (0 = default) |
7477
| `--max-memory <n>` | Global memory limit (bytes, 0 = auto) |
78+
| `--log-level <level>` | Log level: `debug`\|`info`\|`warn`\|`error`\|`fatal`\|`none` (default: `none`) |
79+
| `--log-to-file` | Write logs to `<db_path>/LOG` instead of stderr |
80+
| `--log-truncation-at <n>` | Log truncation size in bytes (0 = no truncation) |
81+
| `--object-store-fs <root_dir>` | Enable filesystem object-store connector. Auto-enables unified memtable mode |
82+
| `--obj-cache-path <dir>` | Local cache directory for object store (default: `<db_path>`) |
83+
| `--obj-cache-max-bytes <n>` | Maximum local cache size in bytes (0 = unlimited) |
84+
| `--obj-replica-mode` | Open the database in read-only replica mode |
85+
| `--obj-replica-sync-interval <us>` | Replica MANIFEST poll interval (default: 5000000) |
86+
| `--obj-wal-sync-on-commit` | Upload the WAL to the object store after every commit (RPO=0) |
7587

7688
**Examples**
7789
```
@@ -83,12 +95,22 @@ Opened database at './mydb' (unified memtable)
8395
8496
admintool> open ./mydb --unified --cache-size 134217728 --flush-threads 4
8597
Opened database at './mydb' (unified memtable)
98+
99+
admintool> open ./mydb --log-level info --log-to-file
100+
Opened database at './mydb'
101+
102+
admintool> open ./mydb --object-store-fs /mnt/objects
103+
Opened database at './mydb' (object-store fs:/mnt/objects)
86104
```
87105

88106
:::note[Unified Memtable Mode]
89107
When `--unified` is set, all column families share a single skip list and WAL instead of each column family maintaining its own. A transaction touching N column families results in 1 WAL write instead of N. On-disk SSTables remain per-column-family. This mode is beneficial for write-heavy multi-CF workloads.
90108
:::
91109

110+
:::note[Filesystem Object Store]
111+
`--object-store-fs <root_dir>` attaches a filesystem-backed object-store connector that mirrors objects under the given directory. This is intended for testing and local replication scenarios. Object-store mode automatically enables unified memtable mode. The connector is destroyed when the database is closed. Combine with `--obj-cache-max-bytes`, `--obj-replica-mode`, `--obj-replica-sync-interval`, and `--obj-wal-sync-on-commit` to tune behavior.
112+
:::
113+
92114
### close
93115
Close the current database.
94116
```
@@ -158,6 +180,11 @@ cf-create <name> [options]
158180
| `--l0-stall <n>` | L0 queue stall threshold |
159181
| `--level-size-ratio <n>` | Level size multiplier |
160182
| `--min-levels <n>` | Minimum LSM levels |
183+
| `--dividing-level-offset <n>` | Compaction dividing level offset |
184+
| `--tombstone-density-trigger <ratio>` | Tombstone density above which compaction priority escalates (`0.0` to `1.0`, `0` disables) |
185+
| `--tombstone-density-min-entries <n>` | Minimum entry count for an SSTable to be considered by the density trigger |
186+
| `--object-lazy-compaction` / `--no-object-lazy-compaction` | Lazy compaction in object-store mode (doubles the L1 trigger, reducing remote I/O) |
187+
| `--object-prefetch-compaction` / `--no-object-prefetch-compaction` | Prefetch all input SSTables in parallel before a compaction merge (default: enabled) |
161188

162189
**Examples**
163190
```
@@ -242,8 +269,9 @@ cf-stats <name>
242269
- Memtable size, levels, total keys
243270
- Data size, avg key/value sizes
244271
- Read amplification, cache hit rate
245-
- Full configuration (compression, bloom filter, sync mode, etc.)
246-
- Per-level SSTable counts and sizes
272+
- Full configuration (compression, bloom filter, sync mode, dividing level offset, tombstone density trigger and minimum, object-store lazy/prefetch compaction, etc.)
273+
- Per-level SSTable counts, sizes, key counts, and tombstone counts
274+
- Tombstone observability: total tombstones, database-wide ratio, and the worst single-SSTable tombstone density (with the level it lives on)
247275
- B+tree statistics (if enabled)
248276

249277
### cf-status
@@ -276,8 +304,10 @@ All options from `cf-create` are supported except `--btree` and `--comparator` (
276304
- `--block-index-prefix-len`, `--index-sample-ratio`, `--no-block-indexes` · Block index settings for new SSTables
277305
- `--skip-list-max-level`, `--skip-list-probability` · Skip list settings for new memtables
278306
- `--isolation` · Default transaction isolation level
279-
- `--level-size-ratio`, `--min-levels` · LSM level sizing
307+
- `--level-size-ratio`, `--min-levels`, `--dividing-level-offset` · LSM level sizing
280308
- `--l1-trigger`, `--l0-stall` · Compaction and backpressure thresholds
309+
- `--tombstone-density-trigger`, `--tombstone-density-min-entries` · Tombstone-density compaction escalation
310+
- `--object-lazy-compaction` / `--no-object-lazy-compaction`, `--object-prefetch-compaction` / `--no-object-prefetch-compaction` · Object-store mode tuning
281311
- `--min-disk-space` · Minimum disk space required
282312

283313
**Non-updatable settings**
@@ -293,6 +323,30 @@ admintool(./mydb)> cf-update cache --write-buffer-size 268435456 --no-persist
293323
Configuration updated for 'cache' (in-memory only)
294324
```
295325

326+
### cf-config-save
327+
Save the current column family configuration to an INI file. The optional `section_name` defaults to the column family name.
328+
```
329+
cf-config-save <cf> <ini_file> [section_name]
330+
```
331+
332+
**Example**
333+
```
334+
admintool(./mydb)> cf-config-save users ./users.ini
335+
Saved configuration of 'users' to './users.ini' (section [users])
336+
```
337+
338+
### cf-config-load
339+
Create a column family by loading its configuration from an INI file section. Useful for replicating a tuned configuration across databases or for templating column families.
340+
```
341+
cf-config-load <ini_file> <section_name> <cf_name>
342+
```
343+
344+
**Example**
345+
```
346+
admintool(./mydb)> cf-config-load ./users.ini users users_replica
347+
Created column family 'users_replica' from './users.ini' [users]
348+
```
349+
296350
## Key-Value Operations
297351

298352
### put
@@ -323,6 +377,22 @@ Delete a key.
323377
delete <cf> <key>
324378
```
325379

380+
### single-delete
381+
Tombstone a key with single-delete semantics. Compaction can drop the put and the tombstone together as soon as both appear in the same merge input, rather than carrying the tombstone forward to the largest level.
382+
```
383+
single-delete <cf> <key>
384+
```
385+
386+
:::caution[When to use]
387+
`single-delete` is only safe when each key is put at most once between any two single-deletes (and at most once before the first single-delete on that key). Violating the contract can leave older puts visible after the tombstone. Prefer `delete` for any workload that issues repeated updates to the same key.
388+
:::
389+
390+
**Example**
391+
```
392+
admintool(./mydb)> single-delete users user:1
393+
OK
394+
```
395+
326396
### scan
327397
Scan all keys in a column family.
328398
```
@@ -483,6 +553,31 @@ Trigger compaction on a column family.
483553
compact <cf>
484554
```
485555

556+
### compact-range
557+
Run a synchronous compaction over a specific key range. Only SSTables whose minimum and maximum keys overlap the requested range participate in the merge, so the work and I/O are bounded to the affected portion of the LSM tree rather than the whole column family.
558+
```
559+
compact-range <cf> <start_key> <end_key>
560+
```
561+
562+
**Behavior**
563+
- Synchronous, blocks the caller until the merge commits or fails
564+
- Selects only SSTables whose key range overlaps `[start_key, end_key)`
565+
- Applies the same emit-loop logic as background compactions (tombstone reclamation, single-delete pair cancellation, sequence-based deduplication, value recompression)
566+
- Output SSTables are committed to the manifest atomically and old inputs are marked for deletion
567+
568+
**Use cases**
569+
- Bulk reclaim after a large range delete, where waiting for natural compaction would leave tombstones on disk
570+
- Tenant eviction or sliding-window expiration that does not fit TTL semantics
571+
- Post-import cleanup of a known key range
572+
- Operational counterpart to the automatic tombstone density trigger when an operator wants reclaim now rather than at the next threshold crossing
573+
574+
**Example**
575+
```
576+
admintool(./mydb)> compact-range users tenant_42: tenant_42;
577+
Compacting range 'users' [tenant_42: .. tenant_42;)...
578+
Range compaction completed for 'users'
579+
```
580+
486581
### flush
487582
Flush memtable to disk.
488583
```

src/content/docs/reference/kafka.md

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ Switching from RocksDB to TidesDB requires no changes to your stream topology. Y
3434
<dependency>
3535
<groupId>com.tidesdb</groupId>
3636
<artifactId>tidesdb-kafka</artifactId>
37-
<version>0.3.1</version>
37+
<version>0.4.0</version>
3838
</dependency>
3939
```
4040

@@ -134,6 +134,7 @@ These settings control the TidesDB database instance that backs the state store.
134134
| `maxMemoryUsage` | long | 0 (auto) | Global memory limit in bytes; 0 lets TidesDB auto-detect (50% of system RAM) |
135135
| `logToFile` | boolean | false | Write TidesDB logs to a file instead of stderr |
136136
| `logTruncationAt` | long | 24 MB | Log file truncation size; 0 disables truncation |
137+
| `maxConcurrentFlushes` | int | 0 (library default) | Global semaphore on in-flight memtable flushes across all column families; 0 inherits the engine default |
137138
| `objectStoreFsPath` | String | null | Filesystem path for object store connector; null disables object store mode |
138139
| `objectStoreConfig` | ObjectStoreConfig | null | Object store behavior configuration; null uses defaults |
139140
| `unifiedMemtable` | boolean | false | Enable unified memtable mode (single memtable + WAL for all CFs) |
@@ -171,6 +172,8 @@ Each state store maps to a single TidesDB column family. These settings control
171172
| `dividingLevelOffset` | int | 2 | Compaction dividing level offset |
172173
| `minDiskSpace` | long | 100 MB | Minimum free disk space required before writes are rejected |
173174
| `comparatorName` | String | "" (memcmp) | Custom comparator name; empty uses default binary comparison |
175+
| `tombstoneDensityTrigger` | double | 0.0 (disabled) | Per-SSTable tombstone density above which compaction priority escalates; range 0.0 to 1.0 |
176+
| `tombstoneDensityMinEntries` | long | 1024 | Minimum entry count for an SSTable to be considered by the tombstone density trigger |
174177
| `objectLazyCompaction` | boolean | false | Compact less aggressively in object store mode |
175178
| `objectPrefetchCompaction` | boolean | true | Download all inputs before merge in object store mode |
176179

@@ -337,8 +340,17 @@ System.out.println("Data size: " + stats.getTotalDataSize());
337340
System.out.println("Memtable size: " + stats.getMemtableSize());
338341
System.out.println("Read amplification: " + stats.getReadAmp());
339342
System.out.println("Cache hit rate: " + stats.getHitRate());
343+
344+
// Tombstone observability
345+
System.out.println("Total tombstones: " + stats.getTotalTombstones());
346+
System.out.printf("Tombstone ratio: %.2f%%%n", stats.getTombstoneRatio() * 100.0);
347+
System.out.printf("Worst SSTable density: %.2f%% at level %d%n",
348+
stats.getMaxSstDensity() * 100.0, stats.getMaxSstDensityLevel());
349+
long[] levelTombstoneCounts = stats.getLevelTombstoneCounts();
340350
```
341351

352+
`getTotalKeys()` includes the active memtable plus every SSTable, so writes are visible to stats without a prior flush. The tombstone observability fields (`getTotalTombstones`, `getTombstoneRatio`, `getMaxSstDensity`, `getMaxSstDensityLevel`, `getLevelTombstoneCounts`) pair with the column family `tombstoneDensityTrigger` and `tombstoneDensityMinEntries` settings to monitor and drive density-based compaction escalation.
353+
342354
**Database-level statistics**
343355
```java
344356
DbStats dbStats = store.getDbStats();
@@ -381,6 +393,19 @@ boolean compacting = store.isCompacting();
381393

382394
Use `purge()` before backup, after bulk deletes, or during maintenance windows. Use `compact()` and `flush()` for non-blocking background work.
383395

396+
### Targeted Range Compaction
397+
398+
`compactRange` runs a synchronous compaction over a specific key range. Only SSTables whose key range overlaps the bounds participate in the merge, so the work and I/O are bounded to the affected portion of the LSM tree.
399+
400+
```java
401+
byte[] start = "tenant_42:".getBytes(StandardCharsets.UTF_8);
402+
byte[] end = "tenant_42;".getBytes(StandardCharsets.UTF_8);
403+
404+
store.compactRange(start, end);
405+
```
406+
407+
A null or empty endpoint means unbounded on that side; both null/empty is rejected (use `compact()` for full-CF compaction). Use this after a large range delete, tenant eviction, or when you want to reclaim space immediately rather than waiting for the natural tombstone density trigger to fire.
408+
384409
### WAL Sync
385410

386411
Force an immediate fsync of the write-ahead log:
@@ -427,6 +452,17 @@ store.updateRuntimeConfig(newConfig, true);
427452

428453
Updatable settings include `writeBufferSize`, `skipListMaxLevel`, `skipListProbability`, `bloomFPR`, `indexSampleRatio`, `syncMode`, and `syncIntervalUs`.
429454

455+
### Single-Delete
456+
457+
`singleDelete` writes a tombstone with the same read semantics as `delete`, but lets compaction drop the put and tombstone together as soon as both appear in the same merge input - rather than carrying the tombstone forward until it reaches the largest active level.
458+
459+
```java
460+
TidesDBStore store = (TidesDBStore) context.getStateStore("my-store");
461+
store.singleDelete(Bytes.wrap("session:42".getBytes()));
462+
```
463+
464+
**Caller contract**: between any two single-deletes on the same key, the key has been put **at most once**. The engine cannot verify this; violating the contract can leave older puts visible after the single-delete. Use only for insert-once / delete-once workloads (session caches, secondary-index entries that are never updated, log-style state with scheduled purges). When in doubt, prefer `delete`.
465+
430466
### Range Cost Estimation
431467

432468
Estimate the cost of iterating between two keys without performing any disk I/O:
@@ -559,6 +595,13 @@ store.renameColumnFamily("old_name", "new_name");
559595
store.dropColumnFamily("old_cf");
560596
```
561597

598+
A handle-based variant accepts a `ColumnFamily` object directly:
599+
600+
```java
601+
ColumnFamily cf = store.getDb().getColumnFamily("old_cf");
602+
store.deleteColumnFamily(cf);
603+
```
604+
562605
### Custom Comparators
563606

564607
Register a custom comparator for use with column families. Built-in comparators include `"memcmp"` (default), `"lexicographic"`, `"uint64"`, `"int64"`, `"reverse"`, and `"case_insensitive"`.

0 commit comments

Comments
 (0)