UnQLite:多语言支持的嵌入式NoSQL数据库深入解析

news2024/9/23 13:29:54

文章目录

    • 1. 引言
    • 2. Key/Value 存储接口
      • 2.1 关键函数
      • 2.2 使用示例
      • 2.3 高级操作:批量文件存储
    • 3. 游标的使用
    • 4. UnQLite-Python使用示例
    • 4. UnQLite数据库引擎架构
      • 5.1 Key/Value存储层
      • 5.2 文档存储层
      • 5.3 可插拔的存储引擎
      • 5.4 事务管理器与分页模块
      • 5.5 虚拟文件系统
    • 6. UNQlite VS SQLite
    • 7. 总结

1. 引言

UnQLite 是一个嵌入式的NoSQL数据库引擎,提供一个无需编写复杂SQL语句的方案,支持任意形式的数据存储。对于需要频繁操作JSON数据的应用来说,UnQLite提供的JSON文档存储和读取特别方便,使得数据操作直观和高效,适合于各种嵌入式应用程序。

核心特性

  • Key/Value存储:灵活的键值存储,类似于Berkeley DB和LevelDB。
  • 事务支持:完整的ACID事务支持,确保数据一致性。
  • 多语言支持:支持C/C++、Python、Go、Perl和Lua等语言。

可以通过以下链接下载:UnQLite 下载页面。

2. Key/Value 存储接口

UnQLite的Key/Value存储接口适合存储原始数据。键和值都被视为字节数组,可以存储任意类型的数据,如字符串、二进制对象等。

2.1 关键函数

  • unqlite_kv_store(): 存储键值对。
  • unqlite_kv_append(): 追加数据到现有的键值对。
  • unqlite_kv_fetch_callback(): 通过回调函数获取数据。
  • unqlite_kv_delete(): 删除指定键的记录。

2.2 使用示例

以下代码介绍如何使用UnQLite的Key/Value存储接口执行基本操作:

#include <unqlite.h>

int main(void) {
  unqlite *pDb;
  int rc;

  /* 打开数据库 */
  rc = unqlite_open(&pDb, "test.db", UNQLITE_OPEN_CREATE);
  if (rc != UNQLITE_OK) {
    return 1; /* 非0返回值表示错误 */
  }

  /* 存储记录 */
  rc = unqlite_kv_store(pDb, "test", -1, "Hello World", 11U);
  if (rc != UNQLITE_OK) {
    unqlite_close(pDb); /* 关闭数据库 */
    return 1;
  }

  /* 追加数据 */
  rc = unqlite_kv_append(pDb, "msg", -1, "Hello, ", 7U);
  if (rc == UNQLITE_OK) {
    rc = unqlite_kv_append_fmt(pDb, "msg", -1, "%d:%d:%d", 10, 16, 53);
  }
  if (rc != UNQLITE_OK) {
    unqlite_close(pDb); /* 关闭数据库 */
    return 1;
  }

  /* 删除记录 */
  rc = unqlite_kv_delete(pDb, "test", -1);
  if (rc != UNQLITE_OK) {
    unqlite_close(pDb); /* 关闭数据库 */
    return 1;
  }

  /* 关闭数据库 */
  rc = unqlite_close(pDb);
  if (rc != UNQLITE_OK) {
    return 1;
  }

  return 0; /* 0表示成功 */
}

2.3 高级操作:批量文件存储

可以将外部文件(如XML、音频文件等)直接存储到UnQLite数据库中,并在需要时通过简单的查询提取。

#include <unqlite.h>

int store_files_in_db(int argc, char *argv[]) {
  unqlite *pDb;
  void *pMap;
  unqlite_int64 iSize;
  int rc;
  int i;

  /* 检查参数数量 */
  if (argc <= 1) {
    return 1; /* 错误:没有文件参数 */
  }

  rc = unqlite_open(&pDb, "test.db", UNQLITE_OPEN_CREATE);
  if (rc != UNQLITE_OK) {
    return 1;
  }

  for (i = 1; i < argc; ++i) {
    const char *zName = argv[i];
    rc = unqlite_util_load_mmaped_file(zName, &pMap, &iSize);
    if (rc != UNQLITE_OK) {
      unqlite_close(pDb);
      return 1;
    }

    rc = unqlite_kv_store(pDb, zName, -1, pMap, (unsigned int)iSize);
    unqlite_util_release_mmaped_file(pMap, iSize);
    if (rc != UNQLITE_OK) {
      unqlite_close(pDb);
      return 1;
    }
  }

  rc = unqlite_close(pDb);
  if (rc != UNQLITE_OK) {
    return 1;
  }

  return 0;
}

3. 游标的使用

游标允许遍历整个数据库的记录,适用于需要顺序访问或修改记录的场景。

游标操作示例

#include <unqlite.h>

/* 假设DataConsumerCallback函数已定义 */

int traverse_records(void) {
  unqlite *pDb;
  unqlite_kv_cursor *pCursor;
  unqlite_int64 iData;
  int rc;

  rc = unqlite_open(&pDb, "test.db", UNQLITE_OPEN_CREATE);
  if (rc != UNQLITE_OK) {
    return 1;
  }

  rc = unqlite_kv_cursor_init(pDb, &pCursor);
  if (rc != UNQLITE_OK) {
    unqlite_close(pDb);
    return 1;
  }

  rc = unqlite_kv_cursor_last_entry(pCursor);
  if (rc != UNQLITE_OK) {
    unqlite_kv_cursor_release(pDb, pCursor);
    unqlite_close(pDb);
    return 1;
  }

  while (unqlite_kv_cursor_valid_entry(pCursor)) {
    /* Consume the key */
    rc = unqlite_kv_cursor_key_callback(pCursor, DataConsumerCallback, 0);
    if (rc != UNQLITE_OK) {
      unqlite_kv_cursor_release(pDb, pCursor);
      unqlite_close(pDb);
      return 1;
    }

    /* Extract data length */
    rc = unqlite_kv_cursor_data(pCursor, NULL, &iData);
    if (rc != UNQLITE_OK) {
      unqlite_kv_cursor_release(pDb, pCursor);
      unqlite_close(pDb);
      return 1;
    }

    /* Consume the data */
    rc = unqlite_kv_cursor_data_callback(pCursor, DataConsumerCallback, 0);
    if (rc != UNQLITE_OK) {
      unqlite_kv_cursor_release(pDb, pCursor);
      unqlite_close(pDb);
      return 1;
    }

    /* Move to the previous record */
    rc = unqlite_kv_cursor_prev_entry(pCursor);
    if (rc != UNQLITE_OK && rc != UNQLITE_DONE) {
      unqlite_kv_cursor_release(pDb, pCursor);
      unqlite_close(pDb);
      return 1;
    }
  }

  unqlite_kv_cursor_release(pDb, pCursor);
  rc = unqlite_close(pDb);
  if (rc != UNQLITE_OK) {
    return 1;
  }

  return 0;
}

4. UnQLite-Python使用示例

下面是如何在 Python 中使用 UnQLite 的简要介绍,并展示了基本的操作示例。
可以通过pip3 install unqlite安装Python组件。

import unqlite  

def main():  
    try:  
        # 打开数据库  
        with unqlite.UnQLite('test.db', unqlite.OPEN_CREATE) as db:  

            # 存储记录  
            db['test'] = 'Hello World'  
            print("Stored record: 'Hello World'")  

            # 追加数据  
            db['msg'] = db.get('msg', '') + 'Hello, '  
            db['msg'] += f"{10}:{16}:{53}"  
            print("Appended to 'msg':", db['msg'])  

            # 删除记录  
            if 'test' in db:  
                del db['test']  
                print("Deleted record: 'test'")  
            else:  
                print("Record 'test' not found.")  

            # 检查 'test' 是否已经删除  
            if 'test' in db:  
                print("Failed to delete record 'test'.")  
            else:  
                print("Record 'test' successfully deleted.")  

    except Exception as e:  
        print(f"Error: {e}")  

if __name__ == "__main__":  
    main()

4. UnQLite数据库引擎架构

在这里插入图片描述
UnQLite采用分层架构设计,主要由以下几个关键组件构成:

5.1 Key/Value存储层

UnQLite的核心是一个标准的键/值存储层,类似于BerkeleyDB和LevelDB。它支持ACID事务和并发读取,键和值均为字节数组,能存储各种类型的数据(如ASCII字符串、二进制数据)。该层通过一组接口与主机应用程序交互,接口包括unqlite_kv_store()unqlite_kv_append()unqlite_kv_fetch_callback()等。

5.2 文档存储层

文档存储层用于存储JSON文档,由Jx9编程语言驱动。Jx9是一种嵌入式脚本语言,具备图灵完备性和动态类型特性,语法类似于C和JavaScript。作为扩展语言,Jx9允许在数据库层直接操作JSON格式的数据,提供了强大的文档处理能力。

5.3 可插拔的存储引擎

UnQLite支持多种可插拔的存储引擎,如Hash、B+树、R+树、LSM等。内置的存储引擎包括用于持久化数据库的虚拟线性哈希(VLH)引擎和用于内存数据库的哈希表或红黑树引擎。这种设计使得UnQLite可以根据不同应用场景选择最合适的存储引擎。

5.4 事务管理器与分页模块

分页模块负责从磁盘读写固定大小的块(默认为4096字节),并管理缓存。它还提供回滚和原子提交的功能,确保数据操作的安全性和效率。存储引擎通过页面缓存与分页模块进行交互,处理数据的修改、提交或回滚请求。

5.5 虚拟文件系统

为了实现跨平台兼容性,UnQLite设计了一个抽象的虚拟文件系统(VFS),用于不同操作系统间的移植。每个操作系统都有其专属的VFS实现,这确保了UnQLite可以在POSIX和Win32/64等系统上运行。

6. UNQlite VS SQLite

  • 缓存机制

    • UnQLite首次查询较慢,涉及磁盘访问和数据预处理(如FastJSON解码)。
    • 后续查询利用内存中的缓存,速度更快。
  • 性能测试结果

    • UnQLite内存中
      • 存储:901.9毫秒
      • 查询:2586毫秒
    • UnQLite本地磁盘上
      • 存储:15223.3毫秒
      • 查询:114.2毫秒
    • SQLite内存中
      • 存储:9507毫秒
      • 查询:105毫秒
  • 性能比较

    • 内存中,UnQLite存储速度比SQLite快,但查询速度较慢。
    • 本地磁盘上,UnQLite查询速度比SQLite快,但存储速度较慢。

7. 总结

UnQLite采用分层设计和灵活架构,能够满足多种嵌入式数据库需求。它支持多种编程语言,使用简单,易于上手。除了键值存储外,UnQLite还具备强大的文档存储和跨平台功能。通过结合文档存储、游标和键值接口,也可以开发出复杂的嵌入式数据库应用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2071425.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

右值引用与左值引用

目录 1. 左值与右值2. 左值引用与右值引用 1. 左值与右值 2. 左值引用与右值引用

千益畅行,旅游卡,案例分享

旅游卡作为新旅游这个赛道&#xff0c;到处都是金矿&#xff0c;看你怎么去挖&#xff0c;商机无限。千益畅行旅游卡作为旅游卡源头&#xff0c;提供优质完善的服务&#xff0c;你只需要去铺卡搞钱&#xff0c;其他的售后交给我们&#xff01; #旅游卡服务#

使用静态IP为什么比动态IP的人多?

在网络世界中&#xff0c;IP地址就好比我们的身份证&#xff0c;用来标识我们在互联网上的唯一身份。而静态IP与动态IP&#xff0c;则是这“身份证”的两种不同分配方式。 一、静态IP与动态IP的区别 动态IP&#xff1a;动态IP地址如同租住的公寓&#xff0c;用户每次上网时&a…

【Qt】常见控件 —— QWidget(下)

文章目录 QWidget 的 windowlcon 属性使用 qrc文件管理资源qrc的使用方式在项目中创建 qrc文件把图片 导入到qrc 文件中 QWidget 的 windowOpacity属性 QWidget 的 windowlcon 属性 windowlcon 表示 一个窗口的图标 ( 只能针对 顶层窗口使用 ) windowlcon() 表示 获取到控件的…

吴恩达机器学习课后作业-05偏差与方差

偏差与方差 题目欠拟合改进欠拟合影响偏差和方差因素训练集拟合情况训练集和测试集代价函数选择最优lamda 整体代码 训练集:训练模型 验证集︰模型选择&#xff0c;模型的最终优化 测试集:利用训练好的模型测试其泛化能力 #训练集 x_train,y_train data[X],data[ y]#验证集 …

【C++ Primer Plus习题】4.9

问题: 解答: #include <iostream> using namespace std;typedef struct _CandyBar {string brand;float weight;int calorie; }CandyBar;int main() {CandyBar* snack new CandyBar[3];snack[0] {"德芙",2.1,20};snack[1] { "箭牌",2.2,16 };sna…

鸿蒙(API 12 Beta3版)【使用Image完成图片编码】图片开发指导依赖JS对象

开发者可以调用本模块的Native API接口&#xff0c;完成图片编码&#xff0c;即将PixelMap压缩成不同格式的存档图片。 当前支持编码为JPEG、WebP 和 PNG 格式。 适用场景 图片编码转换。 通过传入图片源ImageSource&#xff0c;封装成想要的格式。 图片编辑 编辑PixelMap后…

【C# 】使用List<实体类>

1. 使用List<实体类> 要在C#中使用List<EntityTemp>并实现查找数据输出&#xff0c;首先需要定义EntityTemp类&#xff0c;并创建一个List<EntityTemp>类型的列表。然后&#xff0c;你可以使用LINQ或其他方法来查找和输出数据。 假设EntityTemp类具有一个…

最新最全的Pytest接口自动化测试框架教程

pytest编写的规则&#xff1a; 1、测试文件以test_开头&#xff08;以_test结尾也可以&#xff09; 2、测试类以Test开头&#xff0c;并且不能带有__init__方法 3、测试函数以test_开头 4、断言必须使用assert pytest.main([-s,-v]) &#xff1a;用来执行测试用例 -s 打印prin…

pcdn闲置带宽被动收入必看教程。第六讲:交换机配置实战篇

pcdn闲置带宽被动收入必看教程。第六讲&#xff1a;交换机配置实战篇 本章节将介绍如何通过简单的步骤配置交换机&#xff0c;以汇聚所有宽带并集中管理速率&#xff0c;最终接入服务器或软路由&#xff0c;实现远程管理分配速率给具体的服务器或小主机等。 交换机配置步骤 1…

Redis:Redis为什么快

文章目录 一、Redis为什么快二、Redis的单线程模型三、高效的数据结构1、跳表 四、内存的高效使用五、I/O多路复用机制六、网络优化 一、Redis为什么快 单机的Redis每秒可以支撑十几万的并发&#xff0c;相对于MySQL来说&#xff0c;性能是MySQL的十几倍。速度快主要有一下因素…

Docker快速上手

Docker 前言一、基本组成二、常用命令2.1 Docker服务2.2 image相关命令2.3 Container相关命令 三、Docker Volume 容器卷3.1 匿名挂载3.2 具名挂载 四、Docker 网络模式4.1 bridge桥接模式4.2 host主机模式4.3 None模式4.4 Container模式4.5 Customer模式 前言 本篇文章不再赘…

2024计算机技术与软件专业技术资格考试-系统规划与管理(高级)

2024年报名时间&#xff1a;2024年8月22日10:00-9月2日16:00 2024年考试时间&#xff1a;2024年11月9日-11月12日 计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试是原中国计算机软件专业技术资格和水平考试&#xff08;简称软件考试&#xff09;的完善与发展。…

windows 10x64 22H2专业纯净版2028.8.24

Windows 10 22H2专业版19045.3208&#xff0c;据传这版最稳定&#xff0c;速度快。原版制作&#xff0c;打齐KB5028166和服务堆栈更新KB5028318补丁。 禁用了系统升级&#xff0c;删除Windows Defender&#xff0c;禁用打印机服务&#xff0c;需要安装打印机的自行打开服务Prin…

逆序对的数量——归并排序

逆序对的数量 归并排序的解法&#xff0c;今天自己拿前台样例模拟了一遍才算是入门了归并排序的感觉 #include<bits/stdc.h>using namespace std; typedef long long ll; const int N1e510; int a[N]; int temp[N]; int k;ll mergesort(int q[],int l,int r) {if(l>r)…

string类的使用与实现

标准库中的string类 string类(了解) string类的文档介绍 注意&#xff1a;在使用string类时&#xff0c;必须包含#include头文件以及using namespace std; auto和范围for 在了解string的用法前在学习一个知识&#xff1b; auto关键字 auto是作为一个新的类型指示符来指示编译器…

若依AjaxResult的get(AjaxResult.CODE_TAG)有时返回的200,有时返回的字符串“200“

这个项目是多模块项目&#xff0c;之前通过web json格式&#xff0c;多模块之前传输用的RestTemplate&#xff0c;但是对接其它系统时要用XML就添加了XML的依赖。 原来 原来ajaxResult.get(AjaxResult.CODE_TAG).equals(200)能返回true&#xff0c; 现在get(AjaxResult.CODE…

3.2.6 盘古开天地start_kernel

点击查看系列文章 》 Interrupt Pipeline系列文章大纲-CSDN博客 3.2 内核初始化(盘古开天地) 3.2.1 内核初始化的神话 3.2.2 从头 (Head)开始 3.2.3 从头初始化到身体 3.2.4 宇之内存的空分复用 3.2.5 宙之CPU的时分复用 3.2.6 盘古开天地start_kernel 3.2.6 盘古开天地start_…

abc 366 E+F(曼哈顿距离 x y 两个坐标分别计算)(贪心+01背包)

E题&#xff1a; 题意&#xff1a;给定的 xi yi 。求有多少点 到给人 若干定点 的曼哈顿距离 和 小于等于D. 因为D 最大时 1e6,-1e6<xi<1e6。 所以 可能的 点 的 x 的范围是 [-2e6 2e6] 同理 y 的 范围 一样。 将 x y 分开讨论。 我们可以枚举 某个x 的 个数&#xff0…

聚类:k-Means 和 k-Medoid

1. 前言 在《对静态分析缺陷报告进行聚类&#xff0c;以降低维护成本》 提到使用 k-Medoid 通过相似缺陷的聚类&#xff0c;来减少程序员对大量缺陷分析的工作量。 k-Medoid 和传统的 k-Means 聚类算法有什么差别呢&#xff1f; 简单的说&#xff0c;K-Medoid 算法是一种基于…