#cql #storage #array #nosql #floating-point #filesystem

cql_db

核心CQL数据库功能 - 一个轻量级的基于数组的数据库

6个版本

0.2.4 2020年3月11日
0.2.3 2020年3月5日
0.2.1 2020年2月25日
0.1.0 2020年2月10日

#1585数据库接口

44 每月下载量
用于 6 crates

MIT/Apache

82KB
497

CQLDb

轻量级、可扩展的基于数组的存储解决方案,目前包含以下开箱即用的存储类型(也支持自定义类型)

  • U64(无符号64位整数)
  • F64(64位浮点数)
  • NullableF64(可空64位浮点数)
  • TinyText(255字符UTF-8字符串)

该项目通过将文件系统视为N维数组来工作,从而消除了扫描以查找项的需要。目前,必须在创建数据库时指定维数的数量,然而每个维度(除了最后一个)都可以按需增长。

该项目最初是针对存储大量关系型时间序列数据而构建的,然而我正在寻找在其它项目中探索其他用途的方法。

数据库是单索引的。

项目结构

该项目分为两个核心子项目,cql_dbcql_model,以及每个支持的类型一个子项目,位于 cql_storage_types 文件夹中。

cql_db 子项目包含核心逻辑,该逻辑协调特定类型的逻辑和基于数组的逻辑,使整个系统作为一个数据库运行。它依赖于 cql_model 和 U64 类型。

cql_model 子项目包含由 cql_db 和存储类型消耗的接口,并由所有子项目引用。

存储类型特定项目包含用于从文件读取/写入特定类型的特定代码,实现了 cql_model 子项目中的接口。

要使用此项目,您需要导入 cql_db 子项目,以及您想要使用的每个存储类型,或者 cql_model 和您自己实现的特质的特质的实现 - 如果您想使用其他类型的话。

下面表格中提供了所有已发布组件的Rustdocs(带示例)和crates

仓库链接 Crates 文档 描述
CQL Db crates.io docs.rs 核心CQL数据库引擎
CQL Model crates.io docs.rs 核心CQL数据库模型/接口
U64 crates.io docs.rs 无符号64位整数存储支持
F64 未发布 未发布 64位浮点数存储支持
NullableF64 crates.io docs.rs 支持可空64位浮点数存储
TinyText crates.io docs.rs 支持255字符UTF-8字符串存储

破坏性更改

由于本项目是针对文件系统的数据存储解决方案,一些更改可能会改变底层数据的预期结构,阻止一个版本正确利用在另一个版本上创建的数据库。截至1.0.0版本,次要版本(中间数字)将递增,破坏性版本列在下面的表中。如果您需要在这两个版本之间进行升级,我建议您从早期版本中读取整个数据库,并将其写入新版本的新数据库中,我将尽力改进这一点。请小心。

Crates 破坏性版本 描述
cql_db 0.2.0 在关键文件和数据库文件中进行的更改。提交 048e5337dcaf7c

入门

要开始,选择一个或多个存储类型(例如使用NullableF64),并将其作为依赖项添加到您的Cargo.toml中,同时包含核心cql_db crate

[dependencies]
//... (any existing dependencies you may have)
cql_db = "^0.2"
cql_nullable_f64 = "^0.2"

然后您需要创建一个文件夹,用于存放数据库,然后尝试以下操作

use std::io;
use std::io::{ Cursor, SeekFrom, Seek };
use cql_nullable_f64::{ NullableF64, unpack_stream };

const DATABASE_LOCATION: &str = "PATH_TO_YOUR_DATABASE_DIRECTORY";
const N_VALUES_TO_READ: usize = 3;

pub fn example_cql() -> io::Result<()> {
    let base_point = [1];
    let value1 = Some(-1.6);
    let value3 = Some(5.4);

    // creates a one dimensional database, with a capacity of 3
    cql_db::create_db::<NullableF64>(
        DATABASE_LOCATION,
        &[3]
    )?;

    // writes Some(-1.6) to [0]
    cql_db::write_value::<NullableF64>(
        DATABASE_LOCATION,
        &base_point,
        value1
    )?;

    // writes Some(5.4) to [2]
    cql_db::write_value::<NullableF64>(
        DATABASE_LOCATION,
        &[base_point[0] + 2],
        value3
    )?;

    let mut result: [Option<f64>; N_VALUES_TO_READ] = [None; N_VALUES_TO_READ];
    let mut stream = Cursor::new(Vec::new());

    // reads 3 points from [0] into `stream`
    cql_db::read_to_stream::<NullableF64>(
        DATABASE_LOCATION,
        &mut stream,
        &base_point,
        N_VALUES_TO_READ as u64
    )?;

    // returns to the start of the stream
    stream.seek(SeekFrom::Start(0)).unwrap();
    // unpacks the stream value by value into the result[]
    unpack_stream(&mut stream, N_VALUES_TO_READ, |idx, value| {
        result[idx] = value
    })?;

    assert_eq!(result[0], value1);
    assert_eq!(result[1], None);
    assert_eq!(result[2], value3);
}

更多示例可以在rustdocs中找到。

基准测试

以下提供了U64类型的基准测试,它们相当基础(并且是四舍五入的),目的是给出相对成本的粗略估计。完整的基准测试代码可以在github中找到,可以使用以下命令运行:rustup run nightly cargo bench。其他类型的基准测试可以在该类型的相应文档中找到。

操作 数据库维度 未检查的平均时间(ns) 平均时间(ns)
单点读取 1 2 450 (+/- 300) 7 500 (+/- 600)
单点读取 4 14 850 (+/- 1 000) 37 550 (+/- 2 300)
单点写入 1 2 800 (+/- 400) 7 700 (+/- 400)
单点写入 4 15 400 (+/- 2 500) 37 700 (+/- 3 000)
流读取1个点 1 2 500 (+/- 300) 10 000 (+/- 850)
流读取1个点 4 14 900 (+/- 600) 42 500 (+/- 6 500)
流读取50,000个点 1 27 650 000 (+/- 31 000) 27 630 000 (+/- 180 000)
流读取50,000个点 4 27 660 000 (+/- 1 200 000) 27 620 000 (+/- 480 000)

许可证

根据您的要求,许可协议为以下之一

任选其一。

贡献

除非您明确声明,否则根据Apache-2.0许可证定义的,您有意提交的任何贡献,都应如上所述双重许可,不附加任何额外条款或条件。

依赖项

~120KB