查看源代码 dets (stdlib v6.2)

基于磁盘的项存储。

此模块提供文件上的项存储。在此模块中,存储的项称为对象,是元组,其中一个元素定义为键。Dets 是在文件中存储的键位于相同位置的对象集合。

Mnesia 应用程序使用此模块,并为那些仅对磁盘上高效存储 Erlang 项感兴趣的用户“按原样”提供。许多应用程序只需要在文件中存储一些项。Mnesia 添加了事务、查询和分布式。Dets 文件的大小不能超过 2 GB。如果需要更大的表,可以使用 Mnesia 中的表碎片化。

存在三种类型的 Dets 表

  • set。这种类型的表对于给定的键最多有一个对象。如果插入一个键已存在于表中的对象,则现有对象将被新对象覆盖。
  • bag。这种类型的表对于给定的键有零个或多个不同的对象。
  • duplicate_bag。这种类型的表对于给定的键有零个或多个可能匹配的对象。

Dets 表必须先打开才能更新或读取,完成后必须正确关闭。如果表未正确关闭,Dets 会自动修复该表。如果表很大,这可能需要相当长的时间。当打开表的进程终止时,Dets 表会被关闭。如果许多 Erlang 进程(用户)打开同一个 Dets 表,它们会共享该表。当所有用户都终止或关闭表时,该表会被正确关闭。如果 Erlang 运行时系统异常终止,则 Dets 表不会被正确关闭。

注意

在具有中断处理程序的 Unix 环境中,^C 命令会异常终止 Erlang 运行时系统。

由于 Dets 执行的所有操作都是磁盘操作,因此必须认识到,单个查找操作涉及一系列磁盘寻道和读取操作。因此,Dets 函数比相应的 ets 函数慢得多,尽管 Dets 导出类似的接口。

Dets 将数据组织为线性哈希列表,并且随着更多数据插入表中,哈希列表会平稳增长。文件上的空间管理由所谓的伙伴系统执行。当前实现将整个伙伴系统保留在 RAM 中,这意味着如果表严重碎片化,则会占用相当多的内存。对表进行碎片整理的唯一方法是关闭它,然后使用选项 repair 设置为 force 再次打开它。

请注意,Ets 中的 ordered_set 类型尚未由 Dets 提供,对于固定 ETS 表,firstnext 调用序列的安全使用提供的并发更新支持也有限。这两种功能都可能在 Erlang/OTP 的未来版本中由 Dets 提供。在此之前,必须使用 Mnesia 应用程序(或一些用户实现的锁定方法)来实现安全的并发性。目前,没有 Erlang/OTP 库支持基于磁盘的有序项存储。

如果发生错误,所有 Dets 函数都会返回 {error, Reason}first/1next/2 是例外,它们会使用错误元组退出进程)。如果指定了格式错误的参数,则所有函数都会使用 badarg 消息退出进程。

另请参阅

ets, mnesia, qlc

摘要

类型

match/1match/3 使用的不透明延续。

bchunk/2 使用的不透明延续。

匹配规范,请参阅 ERTS 用户指南中的Erlang 中的匹配规范部分以及 ms_transform 模块。

match_object/1match_object/3 使用的不透明延续。

有关模式的描述,请参阅 ets:match/2

select/1select/3 使用的不透明延续。

函数

返回此节点上所有打开的表的名称列表。

返回表中存储的对象列表。返回对象的精确表示不是公开的。

关闭表。只有打开表的进程才能关闭它。

从表 Name 中删除所有键为 Key 的对象。

几乎以恒定的时间从表中删除所有对象。但是,如果表是固定的,delete_all_objects(T) 等效于 match_delete(T, '_')

从表中删除指定对象的所有实例。如果表类型为 bagduplicate_bag,则可以使用此函数仅删除某些具有指定键的对象。

根据表的内部顺序返回表 Name 中存储的第一个键,如果表为空,则返回 '$end_of_table'

使用额外的参数 AccIn 在表 Name 的连续元素上调用 Function。表元素以未指定的顺序遍历。Function 必须返回一个新累加器,该累加器将传递给下一次调用。如果表为空,则返回 Acc0

删除表 Name 的所有对象,然后插入 ETS 表 EtsTab 的所有对象。对象以未指定的顺序插入。由于调用了 ets:safe_fixtable/2,因此 ETS 表必须是公共的或由调用进程拥有。

返回有关表 Name 的信息,作为元组列表

返回与表 NameItem 关联的信息。除了为 info/1 定义的 {Item, Value} 对之外,还允许以下项

使用调用输入函数 InitFun 创建的对象替换表 Name 的现有对象。

将一个或多个对象插入到表 Name 中。如果已经存在一个键与某些给定对象的键匹配的对象,并且表类型为 set,则旧对象将被替换。

将一个或多个对象插入到表 Name 中。如果已经存在一个键与任何指定对象的键匹配的对象,则不会更新该表,并返回 false。否则,将插入对象并返回 true

如果可以使用选项 {format, bchunk} 使用 init_table/3 初始化表 Name,并使用 bchunk/2 从某个表 T 读取对象,并且调用 info(T, bchunk_format) 返回 BchunkFormat,则返回 true

如果文件 Filename 是 Dets 表,则返回 true,否则返回 false

返回存储在表 Name 中键为 Key 的所有对象列表,例如

匹配存储在表中的一些对象,并以未指定的顺序返回与指定模式匹配的绑定非空列表。表、模式和匹配的对象数量均由 Continuation 定义,该延续由先前对 match/1match/3 的调用返回。

对于与 Pattern 匹配的表 Name 的每个对象,以未指定的顺序返回绑定列表。有关模式的描述,请参阅 ets:match/2。如果 Pattern 的 keypos'th 元素是未绑定的,则会匹配所有表对象。如果 keypos'th 元素是绑定的,则只会匹配具有正确键的对象。

匹配表 Name 的某些或全部对象,并以未指定的顺序返回与 Pattern 匹配的绑定非空列表。有关模式的描述,请参阅 ets:match/2

从表 Name 中删除与 Pattern 匹配的所有对象。有关模式的描述,请参阅 ets:match/2

以未指定的顺序返回存储在表中的某些与给定模式匹配的对象的非空列表。表、模式和匹配的对象数量均由 Continuation 定义,该延续由先前对 match_object/1match_object/3 的调用返回。

以未指定的顺序返回表 Name 中与 Pattern 匹配的所有对象列表。有关模式的描述,请参阅 ets:match/2

匹配存储在表 Name 中的部分或所有对象,并返回一个非空列表,其中包含与 Pattern 匹配的对象,顺序不确定。有关模式的描述,请参阅 ets:match/2

lookup/2 类似,但不返回对象。如果一个或多个表元素具有键 Key,则返回 true,否则返回 false

根据表的内部顺序,返回表 Name 中键 Key1 之后的键,如果没有下一个键,则返回 '$end_of_table'

打开一个已存在的表。如果表没有正确关闭,则会进行修复。返回的引用将用作表名。此函数对于调试目的最有用。

打开一个表。如果文件不存在,则创建一个空的 Dets 表。

返回处理表请求的进程的 pid 所对应的表名,如果没有这样的表,则返回 undefined

如果延续符(Continuation)已经通过外部术语格式(在节点之间发送或存储在磁盘上),则可以使用此函数来恢复由 select/3select/1 返回的不透明延续符。

如果 Fixtrue,则调用进程会(再次)固定表 Name,否则会释放该表。当固定进程终止时,表也会被释放。

将匹配规范应用于存储在表中的某些对象,并返回一个非空的结果列表。表、匹配规范和匹配的对象数量都由 Continuation 定义,而 Continuation 是先前调用 select/1select/3 返回的。

返回将匹配规范 MatchSpec 应用于存储在表 Name 中的全部或部分对象的结果。对象的顺序未指定。有关匹配规范的描述,请参阅 ERTS 用户指南

返回将匹配规范 MatchSpec 应用于存储在表 Name 中的部分或所有对象的结果。对象的顺序未指定。有关匹配规范的描述,请参阅 ERTS 用户指南

从表 Name 中删除每个对象,使得将匹配规范 MatchSpec 应用于该对象会返回 true 值。有关匹配规范的描述,请参阅 ERTS 用户指南。返回已删除对象的数量。

表的对象分布在槽中,从槽 0 开始,到槽 n 结束。返回与槽 I 关联的对象列表。如果 I > n,则返回 '$end_of_table'

确保对表 Name 进行的所有更新都写入磁盘。这也适用于使用标志 ram_file 设置为 true 打开的表。在这种情况下,RAM 文件的内容会被刷新到磁盘。

返回查询列表推导(QLC)查询句柄。qlc 模块提供了一种主要针对 Mnesia 的查询语言,但 qlc 也将 ETS 表、Dets 表和列表识别为数据源。调用 dets:table/1,2 是使 Dets 表 Name 可用于 qlc 的方法。

将 Dets 表 Name 的对象插入到 ETS 表 EtsTab 中。插入对象的顺序未指定。除非被覆盖,否则会保留 ETS 表的现有对象。

以某种未指定的顺序将 Fun 应用于存储在表 Name 中的每个对象。根据 Fun 的返回值采取不同的操作。允许使用以下 Fun 返回值

通过将 Incr 添加到 Pos:th 位置的元素,更新存储在类型为 set 的表 Name 中键为 Key 的对象。返回新的计数器值。如果未指定位置,则更新紧跟在键之后的元素。

类型

链接到此类型

access()

查看源代码 (未导出)
-type access() :: read | read_write.
链接到此类型

auto_save()

查看源代码 (未导出)
-type auto_save() :: infinity | non_neg_integer().
-opaque bindings_cont()

match/1match/3 使用的不透明延续。

-opaque cont()

bchunk/2 使用的不透明延续。

链接到此类型

keypos()

查看源代码 (未导出)
-type keypos() :: pos_integer().
链接到此类型

match_spec()

查看源代码 (未导出)
-type match_spec() :: ets:match_spec().

匹配规范,请参阅 ERTS 用户指南中的Erlang 中的匹配规范部分以及 ms_transform 模块。

链接到此类型

no_slots()

查看源代码 (未导出)
-type no_slots() :: default | non_neg_integer().
链接到此类型

object()

查看源代码 (未导出)
-type object() :: tuple().
-opaque object_cont()

match_object/1match_object/3 使用的不透明延续。

链接到此类型

pattern()

查看源代码 (未导出)
-type pattern() :: atom() | tuple().

有关模式的描述,请参阅 ets:match/2

-opaque select_cont()

select/1select/3 使用的不透明延续。

-type tab_name() :: term().
-type type() :: bag | duplicate_bag | set.

函数

-spec all() -> [tab_name()].

返回此节点上所有打开的表的名称列表。

链接到此函数

bchunk(Name, Continuation)

查看源代码
-spec bchunk(Name, Continuation) -> {Continuation2, Data} | '$end_of_table' | {error, Reason}
                when
                    Name :: tab_name(),
                    Continuation :: start | cont(),
                    Continuation2 :: cont(),
                    Data :: binary() | tuple(),
                    Reason :: term().

返回表中存储的对象列表。返回对象的精确表示不是公开的。

数据列表可以通过将值 bchunk 指定给函数 init_table/3 的选项 format 来用于初始化表。Mnesia 应用程序使用此函数来复制打开的表。

除非使用 safe_fixtable/2 保护表,否则如果同时对表进行更新,则调用 bchunk/2 可能无法按预期工作。

第一次调用 bchunk/2 时,必须提供初始延续符,即原子 start

bchunk/2 返回一个元组 {Continuation2, Data},其中 Data 是一个对象列表。Continuation2 是另一个延续符,将传递给后续调用 bchunk/2。通过一系列对 bchunk/2 的调用,可以提取所有表对象。

当返回所有对象时,bchunk/2 返回 '$end_of_table',如果发生错误,则返回 {error, Reason}

-spec close(Name) -> ok | {error, Reason} when Name :: tab_name(), Reason :: term().

关闭表。只有打开表的进程才能关闭它。

在系统停止之前,必须关闭所有打开的表。如果尝试打开未正确关闭的表,Dets 会自动尝试修复它。

-spec delete(Name, Key) -> ok | {error, Reason} when Name :: tab_name(), Key :: term(), Reason :: term().

从表 Name 中删除所有键为 Key 的对象。

链接到此函数

delete_all_objects(Name)

查看源代码
-spec delete_all_objects(Name) -> ok | {error, Reason} when Name :: tab_name(), Reason :: term().

几乎以恒定的时间从表中删除所有对象。但是,如果表是固定的,delete_all_objects(T) 等效于 match_delete(T, '_')

链接到此函数

delete_object(Name, Object)

查看源代码
-spec delete_object(Name, Object) -> ok | {error, Reason}
                       when Name :: tab_name(), Object :: object(), Reason :: term().

从表中删除指定对象的所有实例。如果表类型为 bagduplicate_bag,则可以使用此函数仅删除某些具有指定键的对象。

-spec first(Name) -> Key | '$end_of_table' when Name :: tab_name(), Key :: term().

根据表的内部顺序返回表 Name 中存储的第一个键,如果表为空,则返回 '$end_of_table'

除非使用 safe_fixtable/2 保护表,否则如果同时对表进行更新,则后续调用 next/2 可能无法按预期工作。

如果发生错误,进程将退出并显示错误元组 {error, Reason}。错误元组不会返回,因为它无法与键区分开来。

有两个原因不应使用 first/1next/2:它们效率不高,并且会阻止使用键 '$end_of_table',因为此原子用于指示表的末尾。如果可能,请使用函数 matchmatch_objectselect 来遍历表。

链接到此函数

foldl(Function, Acc0, Name)

查看源代码
-spec foldl(Function, Acc0, Name) -> Acc | {error, Reason}
               when
                   Name :: tab_name(),
                   Function :: fun((Object :: object(), AccIn) -> AccOut),
                   Acc0 :: term(),
                   Acc :: term(),
                   AccIn :: term(),
                   AccOut :: term(),
                   Reason :: term().

等效于 foldr/3

链接到此函数

foldr(Function, Acc0, Name)

查看源代码
-spec foldr(Function, Acc0, Name) -> Acc | {error, Reason}
               when
                   Name :: tab_name(),
                   Function :: fun((Object :: object(), AccIn) -> AccOut),
                   Acc0 :: term(),
                   Acc :: term(),
                   AccIn :: term(),
                   AccOut :: term(),
                   Reason :: term().

使用额外的参数 AccIn 在表 Name 的连续元素上调用 Function。表元素以未指定的顺序遍历。Function 必须返回一个新累加器,该累加器将传递给下一次调用。如果表为空,则返回 Acc0

链接到此函数

from_ets(Name, EtsTab)

查看源代码
-spec from_ets(Name, EtsTab) -> ok | {error, Reason}
                  when Name :: tab_name(), EtsTab :: ets:table(), Reason :: term().

删除表 Name 的所有对象,然后插入 ETS 表 EtsTab 的所有对象。对象以未指定的顺序插入。由于调用了 ets:safe_fixtable/2,因此 ETS 表必须是公共的或由调用进程拥有。

-spec info(Name) -> InfoList | undefined
              when
                  Name :: tab_name(),
                  InfoList :: [InfoTuple],
                  InfoTuple ::
                      {file_size, non_neg_integer()} |
                      {filename, file:name()} |
                      {keypos, keypos()} |
                      {size, non_neg_integer()} |
                      {type, type()}.

返回有关表 Name 的信息,作为元组列表

  • {file_size, integer() >= 0}} - 文件大小,以字节为单位。
  • {filename, file:name/0 } - 存储对象的文件名。
  • {keypos, keypos/0 } - 键的位置。
  • {size, integer() >= 0} - 表中存储的对象数量。
  • {type, type/0 } - 表的类型。
-spec info(Name, Item) -> Value | undefined
              when
                  Name :: tab_name(),
                  Item ::
                      access | auto_save | bchunk_format | hash | file_size | filename | keypos |
                      memory | no_keys | no_objects | no_slots | owner | ram_file | safe_fixed |
                      safe_fixed_monotonic_time | size | type,
                  Value :: term().

返回与表 NameItem 关联的信息。除了为 info/1 定义的 {Item, Value} 对之外,还允许以下项

  • {access, access/0 } - 访问模式。

  • {auto_save, auto_save/0 } - 自动保存间隔。

  • {bchunk_format, binary()} - 一个不透明的二进制文件,描述 bchunk/2 返回的对象格式。该二进制文件可以用作 is_compatible_bchunk_format/2 的参数。

  • {hash, Hash} - 描述哪个 BIF 用于计算存储在 Dets 表中的对象的哈希值。Hash 的可能值

  • {memory, integer() >= 0} - 文件大小,以字节为单位。该值与 file_size 项关联的值相同。

  • {no_keys, integer >= 0()} - 表中存储的不同键的数量。

  • {no_objects, integer >= 0()} - 表中存储的对象数量。

  • {no_slots, {Min, Used, Max}} - 表的槽位数。Min 是最小槽位数,Used 是当前已使用的槽位数,Max 是最大槽位数。

  • {owner, pid()} - 处理 Dets 表请求的进程的 pid。

  • {ram_file, boolean()} - 表是否保存在 RAM 中。

  • {safe_fixed_monotonic_time, SafeFixed} - 如果表是固定的,则 SafeFixed 是一个元组 {FixedAtTime, [{Pid,RefCount}]}FixedAtTime 是表首次被固定的时间,Pid 是固定该表的进程的 pid,RefCount 是该进程固定表的次数。列表中可以有任意数量的进程。如果表未被固定,则 SafeFixed 是原子 false

    FixedAtTime 对应于 erlang:monotonic_time/0 在固定时返回的结果。使用 safe_fixed_monotonic_time时间扭曲安全的

  • {safe_fixed, SafeFixed} - 与 {safe_fixed_monotonic_time, SafeFixed} 相同,只是 FixedAtTime 的格式和值不同。

    FixedAtTime 对应于 erlang:timestamp/0 在固定时返回的结果。请注意,当系统使用单或多 时间扭曲模式 时,这可能会产生奇怪的结果。这是因为使用 safe_fixed 不是 时间扭曲安全的。时间扭曲安全的代码必须使用 safe_fixed_monotonic_time 来代替。

链接到此函数

init_table(Name, InitFun)

查看源代码
-spec init_table(Name, InitFun) -> ok | {error, Reason}
                    when
                        Name :: tab_name(),
                        InitFun :: fun((Arg) -> Res),
                        Arg :: read | close,
                        Res :: end_of_input | {[object()], InitFun} | {Data, InitFun} | term(),
                        Reason :: term(),
                        Data :: binary() | tuple().

等效于 init_table(Name, InitFun, [])

链接到此函数

init_table(Name, InitFun, Options)

查看源代码
-spec init_table(Name, InitFun, Options) -> ok | {error, Reason}
                    when
                        Name :: tab_name(),
                        InitFun :: fun((Arg) -> Res),
                        Arg :: read | close,
                        Res :: end_of_input | {[object()], InitFun} | {Data, InitFun} | term(),
                        Options :: Option | [Option],
                        Option :: {min_no_slots, no_slots()} | {format, term | bchunk},
                        Reason :: term(),
                        Data :: binary() | tuple().

使用调用输入函数 InitFun 创建的对象替换表 Name 的现有对象。

使用此函数而不是调用 insert/2 的原因是效率更高。请注意,输入函数是由处理 Dets 表请求的进程调用的,而不是由调用进程调用的。

当使用参数 read 调用时,假设函数 InitFun 在没有更多输入时返回 end_of_input,或者返回 {Objects, Fun},其中 Objects 是一个对象列表,Fun 是一个新的输入函数。任何其他值 Value 都作为错误 {error, {init_fun, Value}} 返回。每个输入函数都会被精确调用一次,如果发生错误,则最后一个函数会使用参数 close 调用,其回复将被忽略。

如果表类型为 set 且存在多个具有给定键的对象,则会选择其中一个对象。这不一定是输入函数返回的对象序列中具有给定键的最后一个对象。避免重复的键,否则文件会不必要地碎片化。这对于存储在 bag 类型的表中的重复对象也适用。

重要的是,表具有足够数量的槽位来存储对象。如果没有,哈希列表会在 init_table/2 返回时开始增长,这会在一段时间内显著降低对表的访问速度。最小槽位数由 open_file/2 选项 min_no_slots 设置,并由 info/2no_slots 返回。另请参见下面的选项 min_no_slots

参数 Options 是一个 {Key, Val} 元组列表,其中允许以下值

  • {min_no_slots, no_slots()} - 指定要存储在表中的不同键的估计数量。忽略具有相同名称的 open_file/2 选项,除非创建表,在这种情况下,在初始化表时提供估计值可以提高性能。
  • {format, Format} - 指定函数 InitFun 返回的对象的格式。如果 Formatterm(默认值),则假设 InitFun 返回一个元组列表。如果 Formatbchunk,则假设 InitFun 返回由 bchunk/2 返回的 Data。此选项会覆盖选项 min_no_slots
-spec insert(Name, Objects) -> ok | {error, Reason}
                when Name :: tab_name(), Objects :: object() | [object()], Reason :: term().

将一个或多个对象插入到表 Name 中。如果已经存在一个键与某些给定对象的键匹配的对象,并且表类型为 set,则旧对象将被替换。

链接到此函数

insert_new(Name, Objects)

查看源代码
-spec insert_new(Name, Objects) -> boolean() | {error, Reason}
                    when Name :: tab_name(), Objects :: object() | [object()], Reason :: term().

将一个或多个对象插入到表 Name 中。如果已经存在一个键与任何指定对象的键匹配的对象,则不会更新该表,并返回 false。否则,将插入对象并返回 true

链接到此函数

is_compatible_bchunk_format(Name, BchunkFormat)

查看源代码
-spec is_compatible_bchunk_format(Name, BchunkFormat) -> boolean()
                                     when Name :: tab_name(), BchunkFormat :: binary().

如果可以使用选项 {format, bchunk} 使用 init_table/3 初始化表 Name,并使用 bchunk/2 从某个表 T 读取对象,并且调用 info(T, bchunk_format) 返回 BchunkFormat,则返回 true

链接到此函数

is_dets_file(Filename)

查看源代码
-spec is_dets_file(Filename) -> boolean() | {error, Reason}
                      when Filename :: file:name(), Reason :: term().

如果文件 Filename 是 Dets 表,则返回 true,否则返回 false

-spec lookup(Name, Key) -> Objects | {error, Reason}
                when Name :: tab_name(), Key :: term(), Objects :: [object()], Reason :: term().

返回存储在表 Name 中键为 Key 的所有对象列表,例如

2> dets:open_file(abc, [{type, bag}]).
{ok,abc}
3> dets:insert(abc, {1,2,3}).
ok
4> dets:insert(abc, {1,3,4}).
ok
5> dets:lookup(abc, 1).
[{1,2,3},{1,3,4}]

如果表类型为 set,则该函数返回空列表或包含一个对象的列表,因为不能有多个具有给定键的对象。如果表类型为 bagduplicate_bag,则该函数返回任意长度的列表。

请注意,返回的对象的顺序是未指定的。特别是,不反映插入对象的顺序。

-spec match(Continuation) -> {[Match], Continuation2} | '$end_of_table' | {error, Reason}
               when
                   Continuation :: bindings_cont(),
                   Continuation2 :: bindings_cont(),
                   Match :: [term()],
                   Reason :: term().

匹配存储在表中的一些对象,并以未指定的顺序返回与指定模式匹配的绑定非空列表。表、模式和匹配的对象数量均由 Continuation 定义,该延续由先前对 match/1match/3 的调用返回。

当所有表对象都匹配时,将返回 '$end_of_table'

-spec match(Name, Pattern) -> [Match] | {error, Reason}
               when Name :: tab_name(), Pattern :: pattern(), Match :: [term()], Reason :: term().

对于与 Pattern 匹配的表 Name 的每个对象,以未指定的顺序返回绑定列表。有关模式的描述,请参阅 ets:match/2。如果 Pattern 的 keypos'th 元素是未绑定的,则会匹配所有表对象。如果 keypos'th 元素是绑定的,则只会匹配具有正确键的对象。

链接到此函数

match(Name, Pattern, N)

查看源代码
-spec match(Name, Pattern, N) -> {[Match], Continuation} | '$end_of_table' | {error, Reason}
               when
                   Name :: tab_name(),
                   Pattern :: pattern(),
                   N :: default | non_neg_integer(),
                   Continuation :: bindings_cont(),
                   Match :: [term()],
                   Reason :: term().

匹配表 Name 的某些或全部对象,并以未指定的顺序返回与 Pattern 匹配的绑定非空列表。有关模式的描述,请参阅 ets:match/2

返回绑定和延续的元组,除非表为空,在这种情况下将返回 '$end_of_table'。延续符用于通过调用 match/1 来匹配更多对象。

如果 Pattern 的 keypos'th 元素已绑定,则会匹配所有表对象。如果 keypos'th 元素未绑定,则会一次匹配 N 个表对象,直到至少一个对象匹配或到达表的末尾。默认值(由 N 的值 default 表示)是让对象的数量根据对象的大小而变化。具有相同键的所有对象始终同时匹配,这意味着有时可以匹配超过 N 个对象。

始终必须在使用 match/3 之前使用 safe_fixtable/2 保护表,否则在调用 match/1 时可能会发生错误。

链接到此函数

match_delete(Name, Pattern)

查看源代码
-spec match_delete(Name, Pattern) -> ok | {error, Reason}
                      when Name :: tab_name(), Pattern :: pattern(), Reason :: term().

从表 Name 中删除与 Pattern 匹配的所有对象。有关模式的描述,请参阅 ets:match/2

如果 Pattern 的 keypos'th 元素已绑定,则只会匹配具有正确键的对象。

链接到此函数

match_object(Continuation)

查看源代码
-spec match_object(Continuation) -> {Objects, Continuation2} | '$end_of_table' | {error, Reason}
                      when
                          Continuation :: object_cont(),
                          Continuation2 :: object_cont(),
                          Objects :: [object()],
                          Reason :: term().

以未指定的顺序返回存储在表中的某些与给定模式匹配的对象的非空列表。表、模式和匹配的对象数量均由 Continuation 定义,该延续由先前对 match_object/1match_object/3 的调用返回。

当所有表对象都匹配时,将返回 '$end_of_table'

链接到此函数

match_object(Name, Pattern)

查看源代码
-spec match_object(Name, Pattern) -> Objects | {error, Reason}
                      when
                          Name :: tab_name(),
                          Pattern :: pattern(),
                          Objects :: [object()],
                          Reason :: term().

以未指定的顺序返回表 Name 中与 Pattern 匹配的所有对象列表。有关模式的描述,请参阅 ets:match/2

如果 Pattern 的 keypos'th 元素未绑定,则会匹配所有表对象。如果 Pattern 的 keypos'th 元素已绑定,则只会匹配具有正确键的对象。

使用 match_object 函数遍历所有表对象比调用 first/1next/2slot/2 更有效。

链接到此函数

match_object(Name, Pattern, N)

查看源代码
-spec match_object(Name, Pattern, N) -> {Objects, Continuation} | '$end_of_table' | {error, Reason}
                      when
                          Name :: tab_name(),
                          Pattern :: pattern(),
                          N :: default | non_neg_integer(),
                          Continuation :: object_cont(),
                          Objects :: [object()],
                          Reason :: term().

匹配存储在表 Name 中的部分或所有对象,并返回一个非空列表,其中包含与 Pattern 匹配的对象,顺序不确定。有关模式的描述,请参阅 ets:match/2

返回一个对象列表和一个延续符,除非表为空,在这种情况下返回 '$end_of_table'。延续符用于通过调用 match_object/1 来匹配更多对象。

如果 Pattern 的 keypos'th 元素已绑定,则会匹配所有表对象。如果 keypos'th 元素未绑定,则会一次匹配 N 个表对象,直到至少一个对象匹配或到达表的末尾。默认值(由 N 的值 default 表示)是让对象的数量根据对象的大小而变化。具有相同键的所有匹配对象始终在相同的回复中返回,这意味着有时可以返回超过 N 个对象。

始终必须在使用 match_object/3 之前使用 safe_fixtable/2 保护表,否则在调用 match_object/1 时可能会发生错误。

-spec member(Name, Key) -> boolean() | {error, Reason}
                when Name :: tab_name(), Key :: term(), Reason :: term().

lookup/2 类似,但不返回对象。如果一个或多个表元素具有键 Key,则返回 true,否则返回 false

-spec next(Name, Key1) -> Key2 | '$end_of_table' when Name :: tab_name(), Key1 :: term(), Key2 :: term().

根据表的内部顺序,返回表 Name 中键 Key1 之后的键,如果没有下一个键,则返回 '$end_of_table'

如果发生错误,进程将以错误元组 {error, Reason} 退出。

要查找表中的第一个键,请使用 first/1

-spec open_file(Filename) -> {ok, Reference} | {error, Reason}
                   when Filename :: file:name(), Reference :: reference(), Reason :: term().

打开一个已存在的表。如果表没有正确关闭,则会进行修复。返回的引用将用作表名。此函数对于调试目的最有用。

-spec open_file(Name, Args) -> {ok, Name} | {error, Reason}
                   when
                       Name :: tab_name(),
                       Args :: [OpenArg],
                       OpenArg ::
                           {access, access()} |
                           {auto_save, auto_save()} |
                           {estimated_no_objects, non_neg_integer()} |
                           {file, file:name()} |
                           {max_no_slots, no_slots()} |
                           {min_no_slots, no_slots()} |
                           {keypos, keypos()} |
                           {ram_file, boolean()} |
                           {repair, boolean() | force} |
                           {type, type()},
                       Reason :: term().

打开一个表。如果文件不存在,则创建一个空的 Dets 表。

原子 Name 是表名。在对表进行所有后续操作时,必须提供表名。该名称也可以由其他进程使用,并且许多进程可以共享一个表。

如果两个进程通过提供相同的名称和参数打开同一个表,则该表有两个用户。如果一个用户关闭了表,它将保持打开状态,直到第二个用户关闭它。

参数 Args{Key, Val} 元组的列表,其中允许以下值

  • {access, access/0 } - 现有的表可以在只读模式下打开。如果以后在崩溃后重新打开,以只读模式打开的表不会进行自动文件修复算法。默认为 read_write

  • {auto_save, auto_save/0 } - 自动保存间隔。如果间隔是整数 Time,则只要在 Time 毫秒内未访问该表,就会将该表刷新到磁盘。刷新后的表在不受控制的仿真器停止后重新打开时无需修复。如果间隔是原子 infinity,则禁用自动保存。默认为 180000(3 分钟)。

  • {estimated_no_objects, no_slots/0 } - 等效于选项 min_no_slots

  • {file, file:name/0 } - 要打开的文件的名称。默认为表名。

  • {max_no_slots, no_slots/0 } - 要使用的最大槽位数。默认为 32 M,即最大值。请注意,较高的值可能会增加表碎片,而较小的值可以减少碎片,但会牺牲执行时间。

  • {min_no_slots, no_slots/0 } - 通过此标志,可以在创建表时指定估计要存储在表中的不同键的数量,从而提高应用程序性能。默认为 256,这是最小值。

  • {keypos, keypos/0 } - 用作键的每个对象的元素的位置。默认为 1。当我们想存储 Erlang 记录时,显式声明键位置的能力非常方便,其中记录的第一个位置是记录类型的名称。

  • {ram_file, boolean()} - 表是否要保存在 RAM 中。将表保存在 RAM 中听起来可能有些反常,但可以提高应用程序的性能,这些应用程序打开一个表,插入一组对象,然后关闭表。当表关闭时,其内容将写入磁盘文件。默认为 false

  • {repair, Value} - Value 可以是 boolean/0 或者原子 force。该标志指定 Dets 服务器是否调用自动文件修复算法。默认为 true。如果指定了 false,则不尝试修复文件,如果必须修复表,则返回 {error, {needs_repair, FileName}}

    force 表示即使表已正确关闭,也会进行修复。这是一个很少需要的选项。

    如果表已打开,则忽略选项 repair

  • {type, type/0 } - 表类型。默认为 set

-spec pid2name(Pid) -> {ok, Name} | undefined when Pid :: pid(), Name :: tab_name().

返回处理表请求的进程的 pid 所对应的表名,如果没有这样的表,则返回 undefined

此函数仅用于调试。

链接到此函数

repair_continuation(Continuation, MatchSpec)

查看源代码
-spec repair_continuation(Continuation, MatchSpec) -> Continuation2
                             when
                                 Continuation :: select_cont(),
                                 Continuation2 :: select_cont(),
                                 MatchSpec :: match_spec().

如果延续符(Continuation)已经通过外部术语格式(在节点之间发送或存储在磁盘上),则可以使用此函数来恢复由 select/3select/1 返回的不透明延续符。

此函数的原因是 continuation term 包含已编译的匹配规范,因此如果转换为外部 term 格式,则会失效。鉴于原始匹配规范保持不变,可以恢复 continuation,这意味着即使它已存储在磁盘上或另一个节点上,也可以再次在后续的 select/1 调用中使用。

有关更多信息和示例,请参阅 ets 模块。

注意

此函数在应用程序代码中很少需要。它由应用程序 Mnesia 使用,以提供分布式 select/3select/1 序列。正常的应用程序将使用 Mnesia 或使 continuation 不被转换为外部格式。

不使用已编译的匹配规范的外部表示形式的原因是为了性能。它可能会在未来的版本中发生更改,而此接口将保持向后兼容性。

链接到此函数

safe_fixtable(Name, Fix)

查看源代码
-spec safe_fixtable(Name, Fix) -> ok when Name :: tab_name(), Fix :: boolean().

如果 Fixtrue,则调用进程会(再次)固定表 Name,否则会释放该表。当固定进程终止时,表也会被释放。

如果许多进程固定一个表,则该表将保持固定状态,直到所有进程都释放它或终止为止。每个进程都会维护一个引用计数器,并且 N 个连续的固定需要 N 个释放才能释放表。

即使表已固定,也不能保证对 first/1next/2 或 select 和 match 函数的调用按预期工作; ets 模块提供的有限并发性尚未由 Dets 提供。固定表目前仅禁用调整表哈希列表的大小。

如果在表被固定时添加了对象,则在表释放时哈希列表开始增长,这会显著减慢一段时间内对表的访问速度。

-spec select(Continuation) -> {Selection, Continuation2} | '$end_of_table' | {error, Reason}
                when
                    Continuation :: select_cont(),
                    Continuation2 :: select_cont(),
                    Selection :: [term()],
                    Reason :: term().

将匹配规范应用于存储在表中的某些对象,并返回一个非空的结果列表。表、匹配规范和匹配的对象数量都由 Continuation 定义,而 Continuation 是先前调用 select/1select/3 返回的。

当表的所有对象都匹配时,将返回 '$end_of_table'

链接到此函数

select(Name, MatchSpec)

查看源代码
-spec select(Name, MatchSpec) -> Selection | {error, Reason}
                when
                    Name :: tab_name(),
                    MatchSpec :: match_spec(),
                    Selection :: [term()],
                    Reason :: term().

返回将匹配规范 MatchSpec 应用于存储在表 Name 中的全部或部分对象的结果。对象的顺序未指定。有关匹配规范的描述,请参阅 ERTS 用户指南

如果 MatchSpec 的第 keypos 个元素未绑定,则匹配规范将应用于表的所有对象。如果第 keypos 个元素已绑定,则匹配规范仅应用于具有正确键的对象。

使用 select 函数遍历表的所有对象比调用 first/1next/2slot/2 更有效。

链接到此函数

select(Name, MatchSpec, N)

查看源代码
-spec select(Name, MatchSpec, N) -> {Selection, Continuation} | '$end_of_table' | {error, Reason}
                when
                    Name :: tab_name(),
                    MatchSpec :: match_spec(),
                    N :: default | non_neg_integer(),
                    Continuation :: select_cont(),
                    Selection :: [term()],
                    Reason :: term().

返回将匹配规范 MatchSpec 应用于存储在表 Name 中的部分或所有对象的结果。对象的顺序未指定。有关匹配规范的描述,请参阅 ERTS 用户指南

将返回应用匹配规范的结果的元组和一个 continuation,除非表为空,在这种情况下将返回 '$end_of_table'。当通过调用 select/1 匹配更多对象时,将使用该 continuation。

如果 MatchSpec 的第 keypos 个元素已绑定,则匹配规范将应用于表中具有正确键的所有对象。如果 MatchSpec 的第 keypos 个元素未绑定,则匹配规范将应用于表的所有对象,一次 N 个对象,直到至少一个对象匹配或到达表末尾为止。默认值(由给 N 赋值 default 表示)是让对象的数量根据对象的大小而变化。具有相同键的所有对象始终同时处理,这意味着匹配规范可以应用于超过 N 个对象。

在调用 select/3 之前,始终必须使用 safe_fixtable/2 保护表,否则在调用 select/1 时可能会发生错误。

链接到此函数

select_delete(Name, MatchSpec)

查看源代码
-spec select_delete(Name, MatchSpec) -> N | {error, Reason}
                       when
                           Name :: tab_name(),
                           MatchSpec :: match_spec(),
                           N :: non_neg_integer(),
                           Reason :: term().

从表 Name 中删除每个对象,使得将匹配规范 MatchSpec 应用于该对象会返回 true 值。有关匹配规范的描述,请参阅 ERTS 用户指南。返回已删除对象的数量。

如果 MatchSpec 的第 keypos 个元素已绑定,则匹配规范仅应用于具有正确键的对象。

-spec slot(Name, I) -> '$end_of_table' | Objects | {error, Reason}
              when Name :: tab_name(), I :: non_neg_integer(), Objects :: [object()], Reason :: term().

表的对象分布在槽中,从槽 0 开始,到槽 n 结束。返回与槽 I 关联的对象列表。如果 I > n,则返回 '$end_of_table'

-spec sync(Name) -> ok | {error, Reason} when Name :: tab_name(), Reason :: term().

确保对表 Name 进行的所有更新都写入磁盘。这也适用于使用标志 ram_file 设置为 true 打开的表。在这种情况下,RAM 文件的内容会被刷新到磁盘。

请注意,保存在 RAM 中的空间管理数据结构(伙伴系统)也会写入磁盘。如果表碎片化,则可能需要一些时间。

-spec table(Name) -> QueryHandle when Name :: tab_name(), QueryHandle :: qlc:query_handle().

等效于 table(Name, [])

-spec table(Name, Options) -> QueryHandle
               when
                   Name :: tab_name(),
                   Options :: Option | [Option],
                   Option :: {n_objects, Limit} | {traverse, TraverseMethod},
                   Limit :: default | pos_integer(),
                   TraverseMethod :: first_next | select | {select, match_spec()},
                   QueryHandle :: qlc:query_handle().

返回查询列表推导(QLC)查询句柄。qlc 模块提供了一种主要针对 Mnesia 的查询语言,但 qlc 也将 ETS 表、Dets 表和列表识别为数据源。调用 dets:table/1,2 是使 Dets 表 Name 可用于 qlc 的方法。

当对键位置只有简单限制时,qlc 使用 dets:lookup/2 来查找键。当无法做到这一点时,将遍历整个表。选项 traverse 确定如何执行此操作。

  • first_next - 通过调用 dets:first/1dets:next/2,一次遍历一个键。

  • select - 通过调用 dets:select/3dets:select/1 遍历表。选项 n_objects 确定返回的对象数(select/3 的第三个参数)。匹配规范(select/3 的第二个参数)由 qlc 组装。

    • 简单的过滤器会转换为等效的匹配规范。
    • 更复杂的过滤器必须应用于 select/3 返回的所有对象,给定一个匹配所有对象的匹配规范。
  • {select, match_spec/0 } - 与 select 相同,通过调用 dets:select/3dets:select/1 来遍历表。区别在于匹配规范是显式指定的。这就是如何声明无法在 qlc 提供的语法中轻松表达的匹配规范。

以下示例使用显式匹配规范来遍历表

1> dets:open_file(t, []),
ok = dets:insert(t, [{1,a},{2,b},{3,c},{4,d}]),
MS = ets:fun2ms(fun({X,Y}) when (X > 1) or (X < 5) -> {Y} end),
QH1 = dets:table(t, [{traverse, {select, MS}}]).

一个带有隐式匹配规范的示例

2> QH2 = qlc:q([{Y} || {X,Y} <- dets:table(t), (X > 1) or (X < 5)]).

后一个示例等效于前一个示例,可以使用函数 qlc:info/1 进行验证

3> qlc:info(QH1) =:= qlc:info(QH2).
true

qlc:info/1 返回有关查询句柄的信息。在这种情况下,为两个查询句柄返回相同的信息。

-spec to_ets(Name, EtsTab) -> EtsTab | {error, Reason}
                when Name :: tab_name(), EtsTab :: ets:table(), Reason :: term().

将 Dets 表 Name 的对象插入到 ETS 表 EtsTab 中。插入对象的顺序未指定。除非被覆盖,否则会保留 ETS 表的现有对象。

-spec traverse(Name, Fun) -> Return | {error, Reason}
                  when
                      Name :: tab_name(),
                      Fun :: fun((Object) -> FunReturn),
                      Object :: object(),
                      FunReturn :: continue | {continue, Val} | {done, Value} | OtherValue,
                      Return :: [term()] | OtherValue,
                      Val :: term(),
                      Value :: term(),
                      OtherValue :: term(),
                      Reason :: term().

以某种未指定的顺序将 Fun 应用于存储在表 Name 中的每个对象。根据 Fun 的返回值采取不同的操作。允许使用以下 Fun 返回值

  • continue - 继续执行遍历。例如,以下函数可用于打印表的内容

    fun(X) -> io:format("~p~n", [X]), continue end.
  • {continue, Val} - 继续遍历并累积 Val。提供以下函数以在列表中收集表的所有对象

    fun(X) -> {continue, X} end.
  • {done, Value} - 终止遍历并返回 [Value | Acc]

Fun 返回的任何其他值 OtherValue 都会终止遍历并立即返回。

链接到此函数

update_counter(Name, Key, Increment)

查看源代码
-spec update_counter(Name, Key, Increment) -> Result
                        when
                            Name :: tab_name(),
                            Key :: term(),
                            Increment :: {Pos, Incr} | Incr,
                            Pos :: integer(),
                            Incr :: integer(),
                            Result :: integer().

通过将 Incr 添加到 Pos:th 位置的元素,更新存储在类型为 set 的表 Name 中键为 Key 的对象。返回新的计数器值。如果未指定位置,则更新紧跟在键之后的元素。

此函数提供了一种更新计数器的方法,而无需查找对象,通过递增元素来更新对象,并将结果对象再次插入到表中。