erlang ETS与DETS入门

用ETS和DETS存储数据

ets和dets是两个系统模块,可以用来高效存储海量的Erlang数据。ETS是Erlang Term Storage(Erlang数据存储)的缩写,DETS则是Disk ETS(磁盘ETS)的缩写。
表的类型共有4种,分别是异键表(set)同键表(bag)有序异键(ordered set)副本同键(duplicate bag)

创建与销毁ETS表

创建四表
可以看到在异键表中,不允许出现相同键的kv对存在,在同键表中会以最后一个存入的kv为准,而副本同键是允许多个同k的kv对存在的(顺带一提,笔者在编写时忘记做ets:delete操作,打开的表在退出时一定记得关闭,尤其是接下来的dets表)。
需要注意的是,ETS表保存在一个单独的存储区域里,与正常的进程内存无关。可以认为ETS表归创建它的进程(主管进程)所有,当这个进程挂了或者调用ets:delete时,表就会被删除。
创建与删除
ets:new时也有许多参数

-spec ets:new(Name, [Opt]) -> TableId

Name -> 表名原子,[Opt]则是一系列选项
1.其中有表的类型
set | ordered_set | bag | duplicate_bag
2.表的公开/保护/私有
private:主管进程可读可写
public:公共可读可写
protected:公共可读 主管可读可写
3.表的名字是否启用
named_table:通过此属性才能通过Name操作表
4.表的K位置
{keypos, K}:指定Key在第几位(默认第一位)

创建与关闭Dets表

与ets不同的是,dets需要先使dets:open_file/2 打开文件才能使用,且同一个文件可以被多个进程同时打开,如果需要关闭表,得所有打开了这个表的进程都调用了dets:close/1 之后才会关闭。

打开文件(没有则创建)
dets:open_file(table,[{file,study}]).

插入元素
dets:insert(table,{hello,world}).

查找元素
dets:lookup(table,hello).

关闭(Close)
dets:close(table)

通过open_file打开一个名为study的file(没有时会自动创建)
创建dets
可以看到已经成功创建了dets表
插入与查找元素
关闭连接
最重要的一点是不再使用表时一定要close掉连接,否则会抛exception shutdown
与ets相同的时,创建时可以接受多个arg作为参数,主要参数如下表:

Args = [OpenArg]
OpenArg =
    {access, access()} |
    周期刷新表 值为infinity时不刷新表
    {auto_save, auto_save()} |
    {estimated_no_objects, integer() >= 0} |
    {file, file:name()} |
    此选项将表分段,用以优化表关于插入操作时间
    {max_no_slots, no_slots()} |
    {min_no_slots, no_slots()} |
    键的位置
    {keypos, keypos()} |
     它先把元素存储在RAM中,当调用dets:syns(Name)函数或者关闭表时,输出这些元素到文件
    {ram_file, boolean()} |
    指示表非正常关闭时是否需要进行修复
    {repair, boolean() | force} |
    可以为setbag或者duplicate bag
    {type, type()}

其他一些有关ETS与DETS的操作

ETS和DETS表还支持许多尚未在Erlang程序设计19章里没有介绍过的操作。这些操作分为以下几类:

  • 基于模式获取和删除对象;
  • ETS和DETS表之间的相互转换;
  • 查看表的资源占用情况;
  • 修复损坏的DETS表;
  • 让表可视化。

1.基于模式获取和删除对象

% 创建一个ETS表
Table = ets:new(my_table, [named_table,bag]).

% 向表中插入数据
ets:insert(Table, [{apple, 1}, {pear, 2}, {orange, 3}, {grape, 4}, {watermelon, 5}, {apple, 6}]).

% 基于模式获取对象
ets:match(Table, {apple, '$1'}).

% 基于模式删除对象
ets:delete_object(Table, {pear, '$2'}).

在这里插入图片描述

% 打开一个DETS表
dets:open_file(table,[{file,study}]).

% 向表中插入数据
dets:insert(table, [{apple, 1}, {pear, 2}, {orange, 3}, {grape, 4}, {watermelon, 5}]).

% 基于模式获取对象
dets:match(table, {apple, '$1'}).

% 基于模式删除对象
dets:delete(table, {pear, '$2'}).

在这里插入图片描述

2.ETS和DETS表之间的相互转换

% 创建一个ETS表
ets:new(table, [named_table]).

% 向ETS表中插入数据
ets:insert(table, [{apple, 1}, {pear, 2}, {orange, 3}, {grape, 4}, {watermelon, 5}]).

% 将ETS表转换为DETS表
ets:to_dets(table, DetsTab).

3.查看表的资源占用情况

% 创建一个ETS表
Table = ets:new(my_table, [named_table]).

% 获取ETS表的信息,包括资源占用情况
Info = ets:info(Table).

在这里插入图片描述

% 打开一个DETS表
dets:open_file(table,[{file,study}]).

% 获取DETS表的信息,包括资源占用情况
dets:info(table).

在这里插入图片描述

4.让表可视化

% 创建一个ETS表
Table = ets:new(my_table, [named_table]).

% 向ETS表中插入数据
ets:insert(Table, [{1, "value1"}, {2, "value2"}, {3, "value3"}, {4, "value4"}]).

% 将ETS表可视化
ets:tab2list(Table).

ets可视化

一些有用的API以及ETS与DETS的互转

笔者翻阅网上大部分的资料都很少有提及ETS和DETS的相关API操作以及详细介绍ETS与DETS的转化过程。这里是笔者经过学习以及翻阅英文文献后获得的一些学习成果,分享给各位正在学习Ets以及Dets的小伙伴。

ets:insert_new

insert_new
与直接insert不同的是,insert_new只会作用于一下情况:原来的ets表中没有将要插入的数据的Key,比起直接insert能更加保证ets的安全性。
insert之后的结果
可以通过ets:i(TableName)来查看ets中的元素,ets:i()可以查看所有正在内存中运行的ets表。

ets:lookup_element

如果表的类型是 set 或 ordered_set,那么lookup_element函数将返回键为 Key 的对象的第 Pos 个元素
如果表的类型是 bag 或 duplicate_bag,那么该函数将返回键为 Key 的对象的第 Pos 个元素的列表
如果表里没有键为 Key 的对象,函数将以 ==badarg ==的原因退出。
lookup_element
需要注意的是如果在使用ets的相关API时操作不当比如参数不对时会导致ETS异常退出数据丢失!
数据
丢失
如图所示我们使用lookup_element去找一个不存在的Pos位的元素,导致ets异常退出,直接导致ets表丢失

ets:delete_all_objects

功能如名字一般,删除ets表里的所有元素,效果如图:
清除所有元素

ets:tab2list

将ets表中的所有数据转化为列表显示:
转化列表
通过底层实现代码可知,本质上是调用了ets的API -> ets:match_object/2 通过模式匹配取出所有的元素

ets:update_element

update_element
更新ets表中以Key为键的第Pos位的元素为Value,此处代表Key为3的KV对的第二位元素改为13,在图中即表现为第三行元素变为了{3,13}。
值得注意的是,第三个参数是指所找到的值的第pos位置的值更改为value 而不是传的{K,V} 所以key为2的键值对不受影响

ets:tab2file

将ets表转换为文件形式存储
ets转文件
指定文件
把表 Table 转储到文件 Filename。
当转储表时,表的某些信息会在转储开始时存到文件头里。这些信息包括表的类型名字访问权限大小版本是否是一个有命名的表。这也包括一些额外加进来的扩展信息,例如在文件里的对象数量、表头和记录的 MD5 校验值。
如果表是 public 类型的表,并且记录在转储的过程中被添加或删除,那么在表头上的 size 大小值也许跟在文件里的实际记录数量不一致。在转储过程中更新 public 类型的表,并且读取的适合希望验证数据,对扩展信息的某个字段的读取验证处理至少是需要的。

ets:to_dets

将ets转储到dets中
ets转dets
这个操作会在插入数据之前清空DETS文件!

dets:to_ets

相对的,有ets转化dets的操作,自然也有dets转化为ets的操作
转化dets
不过注意,to_ets本身会将Tab这个dets表的内容写入Table这个ets表中,我们使用模式匹配生成了一个新的NewEts,它的内容和Table的内容是一致的!
内容一致

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值