ets(erlang term storage,erlang数据存储),dets(disk erlang term stroage,磁盘erlang数据存储)是erlang内置的两个模块,可以在${ERLANG_HOME}/lib/stdlib-3.4.4/下面找到ets.erl,dets.erl这两个文件。并且借助${ERLANG_HOME}/doc/index.html 中的帮助文档来辅助阅读,这个帮助文档是对所有内置模块的说明。
底层数据结构:散列表,平衡二叉树(仅同键表)
存储类型:元组(也就是表中的每个元素是一个元组,一般元组的第一个元素为键)
存储位置:内存
管理权:归创建的进程所有,只有当进程挂了或者调用了ets:delete时表才会删除。
特点:
关于二进制型存储:大型二进制数据不会存储到ets,而是单独在自己的堆外存储,因此对于二进制的存储非常高效,且这些外部存储使用了垃圾收集机制,如果这个二进制对象没有ets表或进程使用就会被回收。
%% 第一步:创建一个ets表
TableId=ets:new(name,[set,protected,{keypos,1}]).
%% 第二步:插入元素,这里第二个参数也可以是元组列表[{},{}...]
ets:insert(TableId,{elem1,1}).
ets:insert(TableId,{elem2,2}).
%% 第三步:查找元素,查找结果可能是元组,也可能是元组列表,因表类型而定
ets:lookup(TableId,elem1).
ets:lookup(TableId,elem2).
%% 第四步:获取所有元素
All=ets:tab2list(TableId).
%% 第五步:关闭表
ets:delete(TableId).
这些函数在文档里都说明的非常清楚,例如ets:new/2
new(Name, Options) -> tid() | atom()
下面是Options参数的类型定义
Options = [Option]
Option =
Type |
Access |
named_table |
{keypos, Pos} |
{heir, Pid :: pid(), HeirData} |
{heir, none} |
Tweaks
可以发现Options一个列表,里面可以有这7种元素,7种元素有的类型定义在ets.erl文件的头部定义,可以自己去查阅,需要说的就是Type,Access,它们的定义如下
-type access() :: public | protected | private.
-type type() :: set | ordered_set | bag | duplicate_bag.
其中type()的四种值分别对应:异键表,有序异键表,同键表,副本同键表。
一下是四种表说明
值 | 说明 | 作用 |
---|---|---|
set | 异键表 | 各个元组里的键必须是独一无二的 |
ordered_set | 有序异键表 | 在异键表基础上,对键值排序 |
bag | 同键表 | 可以有不止一个元组拥有相同的键,但不能有完全相同的元组 |
duplicate_bag | 副本同键表 | 可以有完全相同的元组 |
对于access,它定义了表的访问权限控制,如下表:
值 | 作用 |
---|---|
public | 任何知道此表标识符的进程都可以读取和写入 |
protected | 只有主管进程可以写入,其它进程只能读取 |
private | 只有主管进程可以读取和写入 |
底层数据结构:线性哈希表
存储类型:元组
存储位置:磁盘
管理权:与ets不同的是,dets需要先使用dets:open_file/2 打开文件才能使用,且同一个文件可以被多个进程同时打开,如果需要关闭表,得所有打开了这个表的进程都调用了dets:close/1 之后才会关闭。
特点:
%% 第一步:打开文件
dets:open_file(tableName,[{file,FileName}]).
%% 第二步:插入元素,元素同样可以是元组列表
dets:insert(tableName,{elem1,1}).
%% 第三步:查看元素,返回同样因表类型而不同,可能是元组列表
dets:lookup(tableName,elem1).
%% 第四步:关闭表
dets:close(tableName).
对于dets没有提供像ets:tab2list这样的函数,但是提供了dets:first 和 dets:next 函数。
这两个函数的作用分别是获得第一个元素的键,根据当前给出的键获得下一个键。
因此可以写出如下遍历方式,其中’$end_of_table’是next函数结束标志。
loop(Table)->
F=dets:first(Table),
loop(Table,F).
loop(_,'$end_of_table') -> void;
loop(Table,Key) ->
%% 对Key键的操作
NextKey=dets:next(Table,Key),
loop(Table,NextKey).
其中dets:open_file/2函数的类型规范如下:
open_file(Name, Args) -> {ok, Name} | {error, Reason}
主要看Args参数,它的类型定义如下:
Args = [OpenArg]
OpenArg =
{access, access()} | %% 重点
{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_file, boolean()} |
{repair, boolean() | force} |
{type, type()} %% 重点
再接着看dets对访问权限及表类型的定义:
access() = read | read_write
type() = bag | duplicate_bag | set
可以发现dets的访问权限和ets完全不一样,只有读
和读写
两个值;而表类型则少了有序异键表ordered_set
。