| Crates.io | vecdb |
| lib.rs | vecdb |
| version | 0.6.1 |
| created_at | 2025-08-09 10:19:48.911965+00 |
| updated_at | 2026-01-20 23:14:11.446726+00 |
| description | High-performance mutable persistent vectors built on rawdb |
| homepage | https://github.com/anydb-rs/anydb |
| repository | https://github.com/anydb-rs/anydb |
| max_upload_size | |
| id | 1787795 |
| size | 612,747 |
High-performance mutable persistent vectors built on rawdb.
push, update, truncate, delete by index with sparse holesBytesVec, ZeroCopyVec (uncompressed)PcoVec, LZ4Vec, ZstdVecEagerVec (stored computations), LazyVecFrom1/2/3 (on-the-fly computation)flush()fjall or redbString, Vec<T>, or dynamic structurescargo add vecdb
use vecdb::{
AnyStoredVec, BytesVec, Database, GenericStoredVec,
ImportableVec, Result, Version
};
use std::path::Path;
fn main() -> Result<()> {
// Open database
let db = Database::open(Path::new("data"))?;
// Create vector with index type usize and value type u64
let mut vec: BytesVec<usize, u64> =
BytesVec::import(&db, "my_vec", Version::TWO)?;
// Push values (buffered in memory)
for i in 0..1_000_000 {
vec.push(i);
}
// Flush writes to rawdb region and syncs to disk
vec.flush()?; // Calls write() internally then flushes region
db.flush()?; // Syncs database metadata
// Sequential iteration
let mut sum = 0u64;
for value in vec.iter()? {
sum = sum.wrapping_add(value);
}
// Random access
let reader = vec.create_reader();
for i in [500, 1000, 10] {
if let Ok(value) = vec.read_at(i, &reader) {
println!("vec[{}] = {}", i, value);
}
}
Ok(())
}
vecdb works with fixed-size types:
u8, i32, f64, etc.[T; N]#[repr(C)]zerocopy::FromBytes + zerocopy::AsBytes (for ZeroCopyVec)Bytes trait (for BytesVec, LZ4Vec, ZstdVec)Pco trait (for PcoVec)Use #[derive(Bytes)] or #[derive(Pco)] from vecdb_derive to enable custom wrapper types.
BytesVec<I, T> - Custom serialization via Bytes trait
use vecdb::{BytesVec, Bytes};
#[derive(Bytes)]
struct UserId(u64);
let mut vec: BytesVec<usize, UserId> =
BytesVec::import(&db, "users", Version::TWO)?;
ZeroCopyVec<I, T> - Zero-copy mmap access (fastest random reads)
use vecdb::ZeroCopyVec;
let mut vec: ZeroCopyVec<usize, u32> =
ZeroCopyVec::import(&db, "raw", Version::TWO)?;
PcoVec<I, T> - Pcodec compression (best for numeric data, excellent compression ratios)
use vecdb::PcoVec;
let mut vec: PcoVec<usize, f64> =
PcoVec::import(&db, "prices", Version::TWO)?;
LZ4Vec<I, T> - LZ4 compression (fast, general-purpose)
use vecdb::LZ4Vec;
let mut vec: LZ4Vec<usize, [u8; 16]> =
LZ4Vec::import(&db, "hashes", Version::TWO)?;
ZstdVec<I, T> - Zstd compression (high compression ratio, general-purpose)
use vecdb::ZstdVec;
let mut vec: ZstdVec<usize, u64> =
ZstdVec::import(&db, "data", Version::TWO)?;
EagerVec<V> - Wraps any stored vector to enable eager computation methods
Stores computed results on disk, incrementally updating when source data changes. Use for derived metrics, aggregations, transformations, moving averages, etc.
use vecdb::EagerVec;
let mut derived: EagerVec<BytesVec<usize, f64>> =
EagerVec::import(&db, "derived", Version::TWO)?;
// Compute methods store results on disk
// derived.compute_add(&source1, &source2)?;
// derived.compute_sma(&source, 20)?;
LazyVecFrom1/2/3<...> - Lazily computed vectors from 1-3 source vectors
Values computed on-the-fly during iteration, nothing stored on disk. Use for temporary views or simple transformations.
use vecdb::LazyVecFrom1;
let lazy = LazyVecFrom1::init(
"computed",
Version::TWO,
source.boxed(),
|i, source_iter| source_iter.get(i).map(|v| v * 2)
);
// Computed during iteration, not stored
for value in lazy.iter() {
// ...
}
// Push values (buffered in memory)
vec.push(42);
vec.push(100);
// write() moves pushed values to storage (visible for reads)
vec.write()?;
// flush() calls write() + region().flush() for durability
vec.flush()?;
db.flush()?; // Also flush database metadata
// Update element at index (works on stored data)
vec.update(5, 999)?;
// Delete element (creates a hole at that index)
let reader = vec.create_reader();
vec.take(10, &reader)?;
drop(reader);
// Holes are tracked and can be checked
if vec.holes().contains(&10) {
println!("Index 10 is a hole");
}
// Reading a hole returns None
let reader = vec.create_reader();
assert_eq!(vec.get_any_or_read(10, &reader)?, None);
Rollback uses stamped change deltas - lightweight compared to full snapshots.
use vecdb::Stamp;
// Create initial state
vec.push(100);
vec.push(200);
vec.stamped_write_with_changes(Stamp::new(1))?;
// Make more changes
vec.push(300);
vec.update(0, 999)?;
vec.stamped_write_with_changes(Stamp::new(2))?;
// Rollback to previous stamp (undoes changes from stamp 2)
vec.rollback()?;
assert_eq!(vec.stamp(), Stamp::new(1));
// Rollback before a stamp (undoes everything including stamp 1)
vec.rollback_before(Stamp::new(1))?;
assert_eq!(vec.stamp(), Stamp::new(0));
Configure number of stamps to keep:
let options = (&db, "vec", Version::TWO)
.into()
.with_saved_stamped_changes(10); // Keep last 10 stamps
let vec = BytesVec::import_with(options)?;
Perfect for:
Vecs persistently on diskZeroCopyVec)PcoVec)EagerVec)Not ideal for:
No features are enabled by default. Enable only what you need:
cargo add vecdb # BytesVec only, no compression or optional features
Available features:
pco - Pcodec compression support (PcoVec)zerocopy - Zero-copy mmap access (ZeroCopyVec)lz4 - LZ4 compression support (LZ4Vec)zstd - Zstd compression support (ZstdVec)derive - Derive macros for Bytes and Pco traitsserde - Serde serialization supportserde_json - JSON output using serde_jsonsonic-rs - Faster JSON using sonic-rsWith Pcodec compression:
cargo add vecdb --features pco,derive
With all compression formats:
cargo add vecdb --features pco,zerocopy,lz4,zstd,derive
Comprehensive examples in examples/:
zerocopy.rs - ZeroCopyVec with holes, updates, and rollbackpcodec.rs - PcoVec with compressionRun examples:
cargo run --example zerocopy --features zerocopy
cargo run --example pcodec --features pco
See vecdb_bench for detailed benchmarks.
vecdb is significantly faster than general-purpose embedded databases for fixed-size data workloads.
For best PcoVec decompression performance on x86_64, compile with BMI and AVX2 instructions enabled:
# .cargo/config.toml
[target.x86_64-unknown-linux-gnu]
rustflags = ["-C", "target-feature=+bmi1,+bmi2,+avx2"]
[target.x86_64-apple-darwin]
rustflags = ["-C", "target-feature=+bmi1,+bmi2,+avx2"]
[target.x86_64-pc-windows-msvc]
rustflags = ["-C", "target-feature=+bmi1,+bmi2,+avx2"]
Or build with:
RUSTFLAGS="-C target-feature=+bmi1,+bmi2,+avx2" cargo build --release