基于 Lua 的高性能本地 kv 数据库 (lua >= 5.3)
3.2.5(2023-06-29)- 去除
db-stream提供的stream方法 - 修复
db-stream的兼容性问题 - 修复若干 bug
- 去除
3.2.4(2023-06-28)- 修改
tostring返回值 - 整理部分代码
- 修复若干 bug
- 修改
3.2.3(2023-06-26)- 删除
no_flush属性 - 新增
buffer_size属性 - 新增
buff方法 - 优化
del方法 - 更换
db-type的序列化算法 - 重构
db-pack扩展 - 支持真正删除成员
- 删除
3.2.2(2023-06-22)- 新增
flush方法 - 新增
no_flush属性 - 修复
db-type扩展的致命性 bug - 新增数据库版本校验
- 新增
3.2.1(2023-05-24)- 新增
db-type扩展
- 新增
3.2.0(2023-02-05)- 新增
db-query扩展 - 修复若干 bug
- 新增
3.1.1(2023-02-04)stream方法改为扩展模块
3.1.0(2023-01-26)- 新增
apply与tidy方法 - 新增
db-pack扩展 - 更换了更高效的序列化算法
- 新增
3.0.0(2022-12-25)- 重构项目
- 区分
integer与double - 支持迭代器遍历
- 支持地址操作成员
- 支持设置地址长度
- 区分表单与子数据库
2.6.0(2022-10-28)- 支持指针操作成员
- 更改
stream的read方法特性
2.5.0(2022-09-16)- 修复若干 bug
- 新增流操作
local db = require "db"默认配置
local data = db.open("data.db")指定配置
local data = db.open({
path = 'data.db', -- 数据库路径
block_size = 4096, -- 簇大小,适当调整可减少hash碰撞
can_each = false, -- 遍历支持
addr_size = db.BIT_32, -- 地址长度
byte_order = db.BYTE_AUTO -- 字节序
})缓冲模式
大幅度提升效率,但需要手动调用
flush方法写入缓冲
local data = db.open({
path = 'data.db',
buffer_size = 4096, -- 设置缓冲区大小
})
-- data:buff(4096) -- 设置缓冲区大小
data:flush() -- 写入缓冲set存储数据fset存储二进制数据
data:set(1, 123) -- integer
data:set(2, 123.0) -- double
data:set(4, true) -- boolean
data:set(5, 'hello') -- string
data:set(6, nil) -- nil
data:set(7, {1, 2, 3}) -- table
data:set('push', function(a, b) -- function
return a + b
end) -- 仅支持lua函数,且会丢失upvalue与调试信息
data:fset('fmt', 'I', 1234) -- 存储二进制数据
data:apply { -- 批量存储数据
a1 = 1, a2 = 2, a3 = 3
}get读取数据fget读取二进制数据
print(data:get(1)) -- 123
print(data:get(2)) -- 123.0
print(data:get(3)) -- 3.1415926
print(data:get(4)) -- true
print(data:get(5)) -- hello
print(data:get(6)) -- nil
print(data:get(7)) -- table
local push = data:get('push')
print(push(123, 456)) -- 579
print(data:fget('fmt', 'I'))-- 1234tips: 经过新版本优化,现已支持真正删除成员
data:del('key') -- 删除成员
-- 以下方法仅用于占位
data:set('key', nil) -- 赋值为nilif data:has('key') then
-- 存在
else
-- 不存在
endfor o in data:each() do -- 返回成员地址对象
print(o.name, data:get(o)) -- 成员地址可作为成员标识使用
end传入
db.TYPE_DB可创建空数据库
data:set('a', db.TYPE_DB) -- 空数据库
local a = data:get('a')
a:set('key', 123)传入实例将自动写入内部数据
data:set('b', db.TYPE_DB {
a = 1, b = 2, c = 3
}) -- 创建子数据库
local b = data:get('b') -- 返回LuaDB对象
print(b:get('c')) -- 3tips: 该功能需绑定
db-stream扩展
local db = require 'db' -- 导入LuaDB
require 'db-stream':bind(db) -- 导入扩展模块并绑定LuaDB传入 db.TYPE_STREAM[index] 可创建存储空间,如 index 为负数,则不填充占位符、
data:set('io', db.TYPE_STREAM[8])调用 get 方法获取数据流对象
local stream = data:get('io')
以下为数据流的api
seek(mode, pos)移动指针- set
数据头 - cur
偏移 - end
数据尾
- set
write(string)写入数据write(fmt, ...)写入二进制数据格式参考string.packread()读取剩余数据read(number)读取指定长度read(fmt)读取二进制数据不支持变长类型
stream:write('abcd') -- 写入数据
stream:write('i', 65535) -- 写入二进制数据
stream:seek('set', 2) -- 移动指针 set数据头 cur偏移 end数据尾
print(stream:read()) -- 读取剩余数据
stream:seek('set') -- 移动指针到数据头
print(stream:read(4)) -- 读取4个字节
print(stream:read('i')) -- 读取二进制数据 仅支持固定字节id成员指针- pointer
指针 - key
成员key - name
成员名称
- pointer
addr成员地址- pointer
指针 - key
成员key - key_size
key长度 - name
成员名称 - addr
地址
- pointer
tips: 使用指针或地址访问成员可避免重复寻址
data:set('a', 123) -- 初始化成员
-- 成员id,无需查找指针,但要读取地址
local a1 = data:id('a')
-- 成员地址,无需读取地址,效率最高
local a2 = data:addr('a')
local v = data:get(a1) -- 使用成员id
data:set(a2, v + 1) --使用成员地址
local a3 = data:addr(a1) -- 成员id转成员地址
local a4 = data:id(a2) -- 成员地址转成员id
print(data:get(a3)) -- 124
print(data:get(a4)) -- 124data:close()tips: 该功能需绑定
db-pack扩展
local db = require 'db' -- 导入LuaDB
require 'db-pack':bind(db) -- 导入扩展模块并绑定LuaDBinput解档output归档
local g = db.open({
path = 'assets/g.db',
can_each = true
})
g:output('assets/g.bin') -- 归档数据
g:close()
local h = db.open('assets/h.db')
h:input('assets/g.bin') -- 解档数据
h:close()tips: 该扩展支持 id 类型,但它们是不可靠的
只有在空数据库中解档才能保证可靠性,除非能够保证节点的 level 有效且未占用
tips: 该功能需绑定
db-query扩展
local db = require 'db' -- 导入LuaDB
require 'db-query':bind(db) -- 导入扩展模块并绑定LuaDB
db.Exp:bind(_G) -- 绑定表达式到环境db:query打开查询对象query:key过滤 keyquery:value过滤 valuequery:find迭代查询query:findone查询单条query:map查询并返回数组query:reset重置位置
该模块查询返回
addr对象,过滤值将使之获得value属性
local f = db.open { -- 打开数据库
path = 'assets/f.db',
can_each = true
}
--打开查询对象
local fq = f:query()
-- 查询单条
fq:findone()
-- 迭代查询50条
for o in fq:find(50) do end
-- 迭代查询剩余全部
for o in fq:find() do end
-- 重置进度
fq:reset()
-- 查询50条 返回数组
fq:map(50)
-- 查询剩余全部 返回数组
fq:map()db.Exp表达式Exp.EQ等于Exp.NE不等于Exp.LT小于Exp.LTE小于等于Exp.GT大于Exp.GTE大于等于Exp.DB匹配子数据库Exp.ALL常量 匹配全部Exp.SIZE表或字符串大小Exp.TABLE匹配 tableExp.TYPE常量表 匹配类型Exp.NOT逻辑 非Exp.AND逻辑 且Exp.OR逻辑 或Exp.REQ正则匹配Exp.IN属于Exp.NIN不属于Exp.RANGE范围Exp.CONTAIN包含Exp.NO_CONTAIN不包含
--打开查询对象
f:query()
:key(CONTAIN('a')) -- 包含字符串 "a"
:value(RANGE(0, 100)) -- 匹配范围 0-100
:map() -- 返回数组f:query()
:value(
AND { -- 逻辑且
TYPE.STRING, -- 匹配字符串类型
REQ '^a', -- 正则匹配开头为a的字符串
OR { -- 逻辑或
IN { 'a', 'b', 'c' }, -- 匹配属于其中的值
IN 'abcdefg', -- 匹配属于其中的字符串
SIZE(LTE(3)) -- 匹配长度小于等于3的字符串或表
}
}
)
:map()f:query()
:value(
DB { -- 匹配 子数据库
a = 1, b = 'b', -- 精确匹配
[ALL] = NE(nil), -- 匹配所有成员 不等于nil
c = TABLE(SIZE(5)) -- 匹配table大小为5
-- 参数2为true 满足其中一个条件即通过
-- 反之为false,不满足其中一个即不通过 默认为false
-- TABLE表达式与DB表达式用法相同
}
)
:map()
-- 自定义表达式
function BEGIN(s)
return function(v)
--- 限制类型为 string
if not TYPE.STRING(v) then return false end
--匹配开头
return v:sub(1, #s) == s
end
end
f:query()
:value(BEGIN('exp'))
:map()tips: 该功能需绑定
db-type扩展
local db = require 'db' -- 导入LuaDB
require 'db-type':bind(db) -- 导入扩展模块并绑定LuaDB该模块重载了所有数据类型,大幅度减少空间占用,且提供了
pointer与addr类型但可能会影响效率,尽管影响非常小
-- 保存指针
data:set('pointer', data:id('a'))
-- 保存地址
data:set('addr', data:addr('b'))| 名称 | 备注 | 模块 |
|---|---|---|
BIT_16 |
地址16位 | db |
BIT_24 |
地址24位 | db |
BIT_32 |
地址32位 | db |
BIT_48 |
地址48位 | db |
BIT_64 |
地址64位 | db |
BYTE_LE |
小端 | db |
BYTE_BE |
大端 | db |
BYTE_AUTO |
跟随系统 | db |
TYPE_DB |
库类型 | db |
TYPE_ID |
指针类型 | db |
TYPE_ADDR |
地址类型 | db |
TYPE_STREAM |
流类型 | db-stream |
| 名称 | 备注 | 模块 |
|---|---|---|
db.open |
打开数据库 | db |
db:reset |
重置数据库 | db |
db:id |
成员id | db |
db:addr |
成员地址 | db |
db:load_id |
加载成员id | db |
db:set |
存储数据 | db |
db:get |
读取数据 | db |
db:del |
删除数据 | db |
db:has |
成员是否存在 | db |
db:fset |
写入二进制数据 | db |
db:fget |
读取二进制数据 | db |
db:each |
遍历成员 | db |
db:buff |
缓冲区大小 | db |
db:flush |
写入缓冲 | db |
db:close |
关闭数据库 | db |
db:apply |
批量存储数据 | db |
db:tidy |
整理碎片表 | db |
db:real_name |
成员真实名称 | db |
db:input |
导入表单 | db-pack |
db:output |
导出表单 | db-pack |
stream:length |
空间长度 | db-stream |
stream:seek |
移动流指针 | db-stream |
stream:write |
写入数据 | db-stream |
stream:read |
读取数据 | db-stream |
db:query |
打开查询对象 | db-query |
query:key |
过滤 key | db-query |
query:value |
过滤 value | db-query |
query:find |
迭代查询 | db-query |
query:findone |
查询单条 | db-query |
query:map |
查询并返回数组 | db-query |
query:reset |
重置位置 | db-query |
query.Exp |
表达式 | db-query |
Exp.EQ |
等于 | db-query |
Exp.NE |
不等于 | db-query |
Exp.LT |
小于 | db-query |
Exp.LTE |
小于等于 | db-query |
Exp.GT |
大于 | db-query |
Exp.GTE |
大于等于 | db-query |
Exp.DB |
匹配子数据库 | db-query |
Exp.ALL |
常量 匹配全部 | db-query |
Exp.SIZE |
表或字符串大小 | db-query |
Exp.TABLE |
匹配 table | db-query |
Exp.TYPE |
常量表 匹配类型 | db-query |
Exp.NOT |
逻辑 非 | db-query |
Exp.AND |
逻辑 且 | db-query |
Exp.OR |
逻辑 或 | db-query |
Exp.REQ |
正则匹配 | db-query |
Exp.IN |
属于 | db-query |
Exp.NIN |
不属于 | db-query |
Exp.RANGE |
范围 | db-query |
Exp.CONTAIN |
包含 | db-query |
Exp.NO_CONTAIN |
不包含 | db-query |
| 名称 | 备注 | 默认值 | 模块 |
|---|---|---|---|
| path | 数据库路径 | nil | db |
| byte_order | 字节序 | db.BYTE_AUTO | db |
| addr_size | 地址位深度 | db.BIT_32 | db |
| can_each | 遍历支持 | false | db |
| block_size | 簇大小 | 4096 | db |
| buffer_size | 缓冲区大小 | 0 | db |