Skip to content

Latest commit

 

History

History
86 lines (74 loc) · 3.21 KB

README.md

File metadata and controls

86 lines (74 loc) · 3.21 KB

MPDB索引数据库

为了解决大规模数据有序索引查询问题, 并且需要实现删除功能, 而且主要运行在嵌入式系统, 还需要快速索引大量数据, 所以设计这个数据库.

功能

  1. 添加数据
  2. 删除数据
  3. 查询数据
  4. 循环覆盖写入

状态码

typedef enum mpdb_err{
    MpdbErr_ERROR = -100,   // 通用错误
    MpdbErr_VERSION,        // 版本错误
    MpdbErr_INIT,           // 初始化错误
    MpdbErr_NULL,           // 空错误
    MpdbErr_HEAD,           // 数据库头错误
    MpdbErr_OK = 0,         // 无错误
}MpdbErr;

移植接口

移植接口, 需要对接Flash操作 快操作大小4K

// 读取接口
MpdbErr Mpdb_read_port(u32 addr, u8 *data, u32 data_size);
// 写入接口
MpdbErr Mpdb_write_port(u32 addr, u8 *data, u32 data_size);
// 擦除接口
MpdbErr Mpdb_erase_port(u32 addr, u32 data_size);
// 获得Flash的大小
u32 Mpdb_capacity_port();
// 擦除所有块
MpdbErr Mpdb_erase_all_port();

// 数据导出操作, 打开输出
MpdbErr Mpdb_export_open_port();
// 输出数据
MpdbErr Mpdb_export_write_port(u32 addr, u8 *data, u32 data_size);
// 结束, 释放资源
void Mpdb_export_close_port();

调用接口

typedef enum mpdb_query_mode{
    MpdbQueryMode_NORMAL,   //普通模式
    MpdbQueryMode_FAST      //快速模式
}MpdbQueryMode;
  • 普通模式: 全部功能的模式
  • 快速模式: 删除功能不生效, 减去查询数据删除标志位的时间, 能将数据查询速度达到算法最快, 数据结构兼容, 普通模式删除的数据在快速模式中查询到.
// 数据库初始化操作
MpdbErr Mpdb_init(Mpdb* mpdb, MpdbQueryMode query_mode);
// 添加数据
MpdbErr Mpdb_add(Mpdb* mpdb, void* data);
// 获得数据库中的数据数量
u32 Mpdb_count(const Mpdb *const mpdb);
// 获得数据能保存多少数据
u32 Mpdb_capacity(const Mpdb *const mpdb);

// 数据库定位
MpdbErr Mpdb_positioning(Mpdb* mpdb, u32 index, MpdbItarContext *context);
// 配合定位操作读取位置的数据, 运行完成后定位会自增一移动, 多次调用实现数据迭代获取
MpdbErr Mpdb_get(Mpdb *const mpdb, MpdbItarContext *context, void *data);

// 删除数据
MpdbErr Mpdb_delete(Mpdb* mpdb, u32 index);
// 数据库复位
MpdbErr Mpdb_reset(Mpdb* mpdb, u32 data_size);
// 数据库导出
MpdbErr Mpdb_export(Mpdb* mpdb);

设计方案

结合Flash块操作的特点来管理数据库
数据库结构:
数据库使用一个块来保存数据库通用状态, 其中比较特别的是 1000个寄存器 它是用来保存下一条数据保存的索引, 提高添加速度, 1000个寄存器只是为了均衡磨损, 延长Flash寿命
每个数据块都有一个头, 保存这个块的状态, 其中保存这块中是否有删除数据, 数据标志寄存器有31byte的空间, 所以在数据块中保存的数据不能太小, 不然数据标志寄存器不够使用. 整个头32byte, 数据库查询只需要查询这个头即可, 不需要扫描数据, 从而提升速度
循环写入的实现方法是有一个数据块标记为数据块头, 在查询中根据这个块的索引偏移查询, 当数据写满时, 数据库会擦除最老的数据块写入数据, 并把第二老的块标记为头