erlang中的ets和dets

文章目录

      • 前言
      • 1> ets(erlang term storage,erlang数据存储)
        • 1.1> 简单使用示例
        • 1.2> 简单说明
        • 1.3> 访问权限及表类型
      • 2> dets(disk erlang term stroage,磁盘erlang数据存储)
        • 2.1> 简单使用示例
        • 2.2> 简单说明


前言

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 中的帮助文档来辅助阅读,这个帮助文档是对所有内置模块的说明。

1> ets(erlang term storage,erlang数据存储)

底层数据结构:散列表,平衡二叉树(仅同键表)

存储类型:元组(也就是表中的每个元素是一个元组,一般元组的第一个元素为键)

存储位置:内存

  • 由于ets存储到内存,因此与dets存储到磁盘相比,就会有查找快易丢失的优缺点。

管理权:归创建的进程所有,只有当进程挂了或者调用了ets:delete时表才会删除。

特点:

  • ets和dets都是进程共享
  • 没有垃圾收集机制

关于二进制型存储:大型二进制数据不会存储到ets,而是单独在自己的堆外存储,因此对于二进制的存储非常高效,且这些外部存储使用了垃圾收集机制,如果这个二进制对象没有ets表或进程使用就会被回收。

1.1> 简单使用示例

%% 第一步:创建一个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).

1.2> 简单说明

这些函数在文档里都说明的非常清楚,例如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

1.3> 访问权限及表类型

可以发现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 只有主管进程可以读取和写入

2> dets(disk erlang term stroage,磁盘erlang数据存储)

底层数据结构:线性哈希表

存储类型:元组

存储位置:磁盘

  • 同理由于存储磁盘,那么就会有查询慢不易丢失的优缺点,且文件最大只能到2GB。

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

特点:

  • 能同时被多个进程管理,但是关闭需要所有进程都调用dets:close/1
  • dets:open_file/2 打开表和磁盘文件时,如果文件不存在则会创建。

2.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).

2.2> 简单说明

其中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

你可能感兴趣的:(erlang,erlang,ets,dets)