一、类型
4种类型
set :table中的每一个Value(Tuple)都是唯一,并且一个Key只能对应一个Value
ordered_set :同set,唯一不同的是table中的Key是有序的
bag :table中的每一个Value都是唯一,但是一个key可以对应多个Value
duplicate_bag :table中每一个key可以对应多个Value,并且允许Value重复
set是默认类型,ordered_sets是唯一有序的
bag,duplicate_bag 虽然在查找效率上差不多,但是在插入元素时差距缺非常大
因为bag虽然允许table中每一个Key对应多个Value,但是它不允许这些Value重复,所以在插入具有相同Key的Value时,它必须与每一个现有元素作对比,
而duplicate_bag 允许table中的Value重复,所以它在插入时就完全不需要考虑这些,只管插,所以效率相对于bag来说很高.
测试:
ordered_set
可以看出ordered_set有着 set的特性,同时会自动排序
bag
duplicate_bag
通过测试进行对比,可以很明显看出bag 和duplicate_bag的区别,一个允许重复,一个不允许重复
二、常见api
1.ets:new(Name, Options) -> tid() | atom()
这个函数用来创建一个名为Name的table(若创建成功,返回一个TableId或者TableName供process引用);Options是一个选项list,用来指定创建table的各种属性,它的值有:
1.set,ordered_set,bag,duplicate_bag:指定创建的table类型。
2.public,private,protected:指定table的访问权限,若是public表示所有process都可以对该table进行读写(只要你知道TableId或者TableName),private表示只有创建表的process才能对table进行读写,而protected则表示所有的process都可以对表进行读取,但是只有创建表的process能够对表进行写操作(ps: ets table仅可以被同一个erlang node中的processes共享)。
3.named_table:若指定了named_table这个属性,就可以使用表名(也就是new函数的第一个参数Name)对表进行操作,而无需使用TableId。
4.{keypos,Pos}:默认使用tuple中第一个元素作为Key,,使用{keypos,Pos}可选择第几个元素作为Key其中Pos就是表示使用tuple中第几个元素作为Key。
5.{heir, Pid, HeirData},{heir,none}:这个heir属性指明当创建table的process终止时,是否有其他process来继承这个table,默认值是{heir,none},表示没有继承者,所以当创建表的process终止时,表也随之被delete;若我们指定了{heir,Pid,HeirData},那么当创建表的process终止时,process identifer为Pid的process将会收到一个消息:{'ETS-TRANSFER',tid(),FromPid,HeirData},这样表的拥有权就转交了
如果你不指定任何Options(即参数值为[]),那么ets将会使用[set, protected, {keypos,1}, {heir,none}, {write_concurrency,false}, {read_concurrency,false}]作为默认值 。
2. ets:insert(Tab, ObjectOrObjects) -> true
这个函数是用来往table里插入数据,其中第一个参数Tab表示需要操作哪一张表,它可以是TableId或者TableName(若创建表时指定了named_table选项),
第二个参数ObjectOrObjects表示需要插入的数据,它可以是一个tuple或者是一个tuple list;注意这个insert方法是一个原子操作,并且对于set或者ordered_set类型table,在插入具有相同Key的Value时,会用新值去替换老值;
ets判断两个Key是否相同,它分为 match 和 compare equal 两种情况:
1.如果两个Key(erlang term)match,那么这两个Key不仅值相同,类型也相同;
2.如果两个Key (erlang term)compare equal, 那么只需要这两个Key的值相同,而无需类型相同(譬如 1.0 compare equal 1,但是1 not match 1.0)
所以若两个Key match,则它们一定compare equal,反过来则不行,那在ets中到底是采用match还是compare equal进行判断与table的类型有关,其中ordered_set采用compare equal方式匹配,其余类型都采用match方式匹配
这是一个set类型table,所以在比较Key时采用match方式进行匹配(既比较类型也比较值),所以它认为1.0和1是两个不同的Key,因此插入了两个Tuole
对于ordered_set类型table,它采用compare equal方式进行匹配(仅比较值),所以它认为1.0和1是两个相同的Key,因此用新值{1.0,1} 替换了老值{1, 1}
3.match(Tab, Pattern) -> [Match]
该方法用来查找table中所有匹配Pattern的tuple并返回tuple中某些或全部元素(这个由pattern指定)
其中Pattern可以包含以下字符
1.一个绑定变量或者任意Erlang Term;
2.一个占位符'_',可以匹配任何Erlang Term;
3.一个变量符'$N' (N可以为0,1,2,3....),该变量指定了match方法需要返回tuple中哪些元素;
若Pattern中包含Key值,那么查找起来非常快速(相当于索引查询),否则需要全表遍历
测试
match与match_object,select的对比
用法:
match:获取 ets 存储数据结构的某几个数据集合。
match_object:1.获取 ets 存储的符合条件的整个结构,只能支持直接值匹配 2.迭代的遍历整个 ets 列表 match_object/3 3.查找指定数据的 ets 列表 match_object/2
select:一般用于条件判定来筛选符合条件的数据和指定格式 (>=, =/=,<,=< 等)
效率对比:
select效率较前两个较为慢一些,特别是 ets 中 key 的查找,效率就更慢了,能用 match_object 的就不要用 select
match函数使用特殊的元组语法(match_pattern)来决定返回什么。
select函数使用特殊的元组语法(match_spec),它是match_pattern的超集,能够指定保护并从结果集中提取元素(而不仅仅是返回匹配的密钥)。
select将match_spec编译成匿名函数,加快运行速度
为此功能提供警卫的能力比仅使用match_pattern(因为它们将首先运行)更快地消除误报。
从结果集中提取元素的能力可以节省您以后必须完成的工作,而不是迭代返回的键来提取数据。