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

文章目录

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

c 复制代码
#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数据库中,并在需要时通过简单的查询提取。

c 复制代码
#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. 游标的使用

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

游标操作示例

c 复制代码
#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组件。

py 复制代码
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还具备强大的文档存储和跨平台功能。通过结合文档存储、游标和键值接口,也可以开发出复杂的嵌入式数据库应用。

相关推荐
qq_529835351 小时前
对计算机中缓存的理解和使用Redis作为缓存
数据库·redis·缓存
月光水岸New3 小时前
Ubuntu 中建的mysql数据库使用Navicat for MySQL连接不上
数据库·mysql·ubuntu
狄加山6753 小时前
数据库基础1
数据库
我爱松子鱼3 小时前
mysql之规则优化器RBO
数据库·mysql
chengooooooo4 小时前
苍穹外卖day8 地址上传 用户下单 订单支付
java·服务器·数据库
Rverdoser5 小时前
【SQL】多表查询案例
数据库·sql
Galeoto5 小时前
how to export a table in sqlite, and import into another
数据库·sqlite
人间打气筒(Ada)5 小时前
MySQL主从架构
服务器·数据库·mysql
leegong231115 小时前
学习PostgreSQL专家认证
数据库·学习·postgresql
喝醉酒的小白5 小时前
PostgreSQL:更新字段慢
数据库·postgresql