This module is an interface to the Erlang built-in term storage
BIFs. These provide the ability to store very large quantities of
data in an Erlang runtime system, and to have constant access
time to the data. (In the case of
Data is organized as a set of dynamic tables, which can store tuples. Each table is created by a process. When the process terminates, the table is automatically destroyed. Every table has access rights set at creation.
Tables are divided into four different types,
The number of tables stored at one Erlang node used to
be limited. This is no longer the case (except by memory usage).
The previous default limit was about 1400 tables and
could be increased by setting the environment variable
Notice that there is no automatic garbage collection for tables.
Even if there are no references to a table from any process, it
is not automatically destroyed unless the owner process
terminates. To destroy a table explicitly, use function
Some implementation details:
In the current implementation, every object insert and look-up operation results in a copy of the object.
Notice the subtle difference between
matching and comparing equal, which is
demonstrated by table types
Two Erlang terms
Two Erlang terms compare equal
if they either are of the same type and value, or if
both are numeric types and extend to the same value, so that
The
The functions in this module exits with reason
This module provides some limited support for concurrent access. All updates to single objects are guaranteed to be both atomic and isolated. This means that an updating operation to a single object either succeeds or fails completely without any effect (atomicity) and that no intermediate results of the update can be seen by other processes (isolation). Some functions that update many objects state that they even guarantee atomicity and isolation for the entire operation. In database terms the isolation level can be seen as "serializable", as if all isolated operations are carried out serially, one after the other in a strict order.
There are different ways to traverse through the objects of a table.
Single-step traversal one key at at time, using
Search with simple match patterns, using
Search with more powerful match specifications, using
Table conversions, using
None of these ways of table traversal will guarantee a consistent table snapshot if the table is also updated during the traversal. Moreover, traversals not done in a safe way, on tables where keys are inserted or deleted during the traversal, may yield the following undesired effects:
Any key may be missed.
Any key may be found more than once.
The traversal may fail with
A table traversal is safe if either
the table is of type
the entire table traversal is done within one ETS function call.
function
Traversals using
1> T = ets:new(t,[ordered_set]), ets:insert(T, {"555-1234", "John Smith"}). true 2> %% Efficient search of all with area code 555 2> ets:match(T,{[$5,$5,$5,$- |'$1'],'$2'}). [["1234","John Smith"]]
Some of the functions use a match specification,
Opaque continuation used by
A match specification, see above.
A compiled match specification.
A table identifier, as returned by
Returns a list of all tables at the node. Named tables are specified by their names, unnamed tables are specified by their table identifiers.
There is no guarantee of consistency in the returned list. Tables
created or deleted by other processes "during" the
Deletes the entire table
Deletes all objects with key
Delete all objects in the ETS table
Delete the exact object
Reads a file produced by
Equivalent to
Reads a file produced by
The only supported option is
If no
If verification is turned on and the file was written with
option
Returns the first key
To find subsequent keys in the table, use
If
If
Fills an already created ETS table with the objects in the
already opened Dets table
If any of the tables does not exist or the Dets table is
not open, a
Pseudo function that by a
The parse transform is provided in the
The fun is very restricted, it can take only a single
parameter (the object to match): a sole variable or a
tuple. It must use the
The return value is the resulting match specification.
Example:
1> ets:fun2ms(fun({M,N}) when N > 3 -> M end). [{{'$1','$2'},[{'>','$2',3}],['$1']}]
Variables from the environment can be imported, so that the following works:
2> X=3. 3 3> ets:fun2ms(fun({M,N}) when N > X -> M end). [{{'$1','$2'},[{'>','$2',{const,3}}],['$1']}]
The imported variables are replaced by match specification
4> ets:fun2ms(fun({M,N}) when N > X, my_fun(M) -> M end). Error: fun containing local Erlang function calls ('my_fun' called in guard) cannot be translated into match_spec {error,transform_error} 5> ets:fun2ms(fun({M,N}) when N > X, is_atom(M) -> M end). [{{'$1','$2'},[{'>','$2',{const,3}},{is_atom,'$1'}],['$1']}]
As shown by the example, the function can be called from the shell also. The fun must be literally in the call when used from the shell as well.
If the
For more information, see
Make process
The process
Notice that this function does not affect option
Displays information about all ETS tables on a terminal.
Browses table
Returns information about table
Indicates if the table is compressed.
The pid of the heir of the table, or
The table identifier.
The key position.
The number of words allocated to the table.
The table name.
Indicates if the table is named.
The node where the table is stored. This field is no longer meaningful, as tables cannot be accessed from other nodes.
The pid of the owner of the table.
The table access rights.
The number of objects inserted in the table.
The table type.
Indicates whether the table uses
Indicates whether the table uses
Returns the information associated with
In addition to the
Indicates if the table is fixed by any process.
If the table has been fixed using
The format and value of
If the table never has been fixed, the call returns
Returns internal statistics about
Replaces the existing objects of table
When called with argument
If the table type is
Inserts the object or all of the objects in list
If the table type is
If the table type is
If the list contains more than one object with
matching keys and the table type is
The entire operation is guaranteed to be
Same as
If
Checks if a term is a valid
compiled
Examples:
The following expression yields
ets:is_compiled_ms(ets:match_spec_compile([{'_',[],[true]}])).
The following expressions yield
MS = ets:match_spec_compile([{'_',[],[true]}]),
Broken = binary_to_term(term_to_binary(MS)),
ets:is_compiled_ms(Broken).
The reason for not having an external representation of compiled match specifications is performance. It can be subject to change in future releases, while this interface remains for backward compatibility.
Returns the last key
To find preceding keys in the table, use
Returns a list of all objects with key
For tables of type
For tables of type
The difference is the same as between
As an example, one can insert an object with
For tables of type
Notice that the time order of object insertions is preserved; the first object inserted with the specified key is the first in the resulting list, and so on.
Insert and lookup times in tables of type
For a table
For tables of type
If no object with key
The difference between
Continues a match started with
When there are no more objects in the table,
Matches the objects in table
A pattern is a term that can contain:
The function returns a list with one element for each matching object, where each element is an ordered list of pattern variable bindings, for example:
6> ets:match(T, '$1'). % Matches every object in table [[{rufsen,dog,7}],[{brunte,horse,5}],[{ludde,dog,5}]] 7> ets:match(T, {'_',dog,'$1'}). [[7],[5]] 8> ets:match(T, {'_',cow,'$1'}). []
If the key is specified in the pattern, the match is very efficient. If the key is not specified, that is, if it is a variable or an underscore, the entire table must be searched. The search time can be substantial if the table is very large.
For tables of type
Works like
If the table is empty,
Use
Deletes all objects that match pattern
Continues a match started with
When there are no more objects in the table,
Matches the objects in table
If the key is specified in the pattern, the match is very efficient. If the key is not specified, that is, if it is a variable or an underscore, the entire table must be searched. The search time can be substantial if the table is very large.
For tables of type
Works like
If the table is empty,
Use
Transforms a
If term
This function has limited use in normal code. It is used by the
Executes the matching specified in a compiled
The matching is executed on each element in
Example:
The following two calls give the same result (but certainly not the same execution time):
Table = ets:new...
MatchSpec = ...
% The following call...
ets:match_spec_run(ets:tab2list(Table),
ets:match_spec_compile(MatchSpec)),
% ...gives the same result as the more common (and more efficient)
ets:select(Table, MatchSpec),
This function has limited use in normal code. It is used by the
Works like
Creates a new table and returns a table identifier that can be used in subsequent operations. The table identifier can be sent to other processes so that a table can be shared between different processes within a node.
Parameter
The table is a
The table is a
The table is a
The table is a
Any process can read or write to the table.
The owner process can read and write to the table. Other processes can only read the table. This is the default setting for the access rights.
Only the owner process can read or write to the table.
If this option is present, the table is registered under its
The function will also return the
Specifies which element in the stored tuples to use
as key. By default, it is the first element, that is,
Notice that any tuple stored in the table must have at
least
Set a process as heir. The heir inherits the table if
the owner terminates. Message
Performance tuning. Defaults to
Option
Notice that this option does not change any guarantees about
Table type
Performance tuning. Defaults to
You typically want to enable this option when concurrent read operations are much more frequent than write operations, or when concurrent reads and writes comes in large read and write bursts (that is, many reads not interrupted by writes, and many writes not interrupted by reads).
You typically do not want to enable this option when the common access pattern is a few read operations interleaved with a few write operations repeatedly. In this case, you would get a performance degradation by enabling this option.
Option
If this option is present, the table data is stored in a more
compact format to consume less memory. However, it will make
table operations slower. Especially operations that need to
inspect entire objects, such as
Returns the next key
To find the first key in the table, use
Unless a table of type
Returns the previous key
To find the last key in an
Renames the named table
Restores an opaque continuation returned by
The reason for this function is that continuation terms
contain compiled match specifications and therefore are
invalidated if converted to external term format. Given that the
original match specification is kept intact, the continuation can
be restored, meaning it can once again be used in subsequent
Examples:
The following sequence of calls fails:
T=ets:new(x,[]),
...
{_,C} = ets:select(T,ets:fun2ms(fun({N,_}=A)
when (N rem 10) =:= 0 ->
A
end),10),
Broken = binary_to_term(term_to_binary(C)),
ets:select(Broken).
The following sequence works, as the call to
T=ets:new(x,[]),
...
MS = ets:fun2ms(fun({N,_}=A)
when (N rem 10) =:= 0 ->
A
end),
{_,C} = ets:select(T,MS,10),
Broken = binary_to_term(term_to_binary(C)),
ets:select(ets:repair_continuation(Broken,MS)).
This function is rarely needed in application code. It is used
by Mnesia to provide distributed
The reason for not having an external representation of a compiled match specification is performance. It can be subject to change in future releases, while this interface remains for backward compatibility.
Fixes a table of type
A process fixes a table by calling
If many processes fix a table, the table remains fixed until all processes have released it (or terminated). A reference counter is kept on a per process basis, and N consecutive fixes requires N releases to release the table.
When a table is fixed, a sequence of
Example:
clean_all_with_value(Tab,X) ->
safe_fixtable(Tab,true),
clean_all_with_value(Tab,X,ets:first(Tab)),
safe_fixtable(Tab,false).
clean_all_with_value(Tab,X,'$end_of_table') ->
true;
clean_all_with_value(Tab,X,Key) ->
case ets:lookup(Tab,Key) of
[{Key,X}] ->
ets:delete(Tab,Key);
_ ->
true
end,
clean_all_with_value(Tab,X,ets:next(Tab,Key)).
Notice that deleted objects are not freed from a fixed table until it has been released. If a process fixes a table but never releases it, the memory used by the deleted objects is never freed. The performance of operations on the table also degrades significantly.
To retrieve information about which processes have fixed which
tables, use
Notice that
Continues a match started with
When there are no more objects in the table,
Matches the objects in table
MatchSpec = [MatchFunction]
MatchFunction = {MatchHead, [Guard], [Result]}
MatchHead = "Pattern as in ets:match"
Guard = {"Guardtest name", ...}
Result = "Term construct"
This means that the match specification is always a list of one or
more tuples (of arity 3). The first element of the tuple is to be
a pattern as described in
The return value is constructed using the "match variables"
bound in
ets:match(Tab,{'$1','$2','$3'})
is exactly equivalent to:
ets:select(Tab,[{{'$1','$2','$3'},[],['$$']}])
And that the following
ets:match_object(Tab,{'$1','$2','$1'})
is exactly equivalent to
ets:select(Tab,[{{'$1','$2','$1'},[],['$_']}])
Composite terms can be constructed in the
ets:select(Tab,[{{'$1','$2','$3'},[],['$$']}])
gives the same output as:
ets:select(Tab,[{{'$1','$2','$3'},[],[['$1','$2','$3']]}])
That is, all the bound variables in the match head as a list. If
tuples are to be constructed, one has to write a tuple of
arity 1 where the single element in the tuple is the tuple
one wants to construct (as an ordinary tuple can be mistaken
for a
Therefore the following call:
ets:select(Tab,[{{'$1','$2','$1'},[],['$_']}])
gives the same output as:
ets:select(Tab,[{{'$1','$2','$1'},[],[{{'$1','$2','$3'}}]}])
This syntax is equivalent to the syntax used in the trace
patterns (see the
The
The
is expressed as follows (
For tables of type
Works like
If the table is empty,
Use
Matches the objects in table
This function can be described as a
The function returns the number of objects matched.
Matches the objects in table
The function returns the number of objects deleted from the table.
The match specification has to return the atom
Matches the objects in the table
The match-and-replace operation for each individual object is guaranteed to be
The match specifiction must be guaranteed to retain the key
of any matched object. If not,
For the moment, due to performance and semantic constraints,
tables of type
The function returns the total number of replaced objects.
Example
For all 2-tuples with a list in second position, add atom
1> T = ets:new(x,[]), ets:insert(T, {key, [1, 2, 3]}). true 2> MS = ets:fun2ms(fun({K, L}) when is_list(L) -> {K, [marker | L]} end). [{{'$1','$2'},[{is_list,'$2'}],[{{'$1',[marker|'$2']}}]}] 3> ets:select_replace(T, MS). 1 4> ets:tab2list(T). [{key,[marker,1,2,3]}]
A generic single object compare-and-swap operation:
[Old] = ets:lookup(T, Key), New = update_object(Old), Success = (1 =:= ets:select_replace(T, [{Old, [], [{const, New}]}])),
Continues a match started with
Example:
1> T = ets:new(x,[ordered_set]).
2> [ ets:insert(T,{N}) || N <- lists:seq(1,10) ].
...
3> {R0,C0} = ets:select_reverse(T,[{'_',[],['$_']}],4).
...
4> R0.
[{10},{9},{8},{7}]
5> {R1,C1} = ets:select_reverse(C0).
...
6> R1.
[{6},{5},{4},{3}]
7> {R2,C2} = ets:select_reverse(C1).
...
8> R2.
[{2},{1}]
9> '$end_of_table' = ets:select_reverse(C2).
...
Works like
Works like
Notice that this is not equivalent to
reversing the result list of a
Sets table options. The only allowed option to be set after the
table has been created is
This function is mostly for debugging purposes, Normally
Returns all objects in slot
Unless a table of type
Dumps table
Equivalent to
Dumps table
When dumping the table, some information about the table is dumped to a header at the beginning of the dump. This information contains data about the table type, name, protection, size, version, and if it is a named table. It also contains notes about what extended information is added to the file, which can be a count of the objects in the file or a MD5 sum of the header and records in the file.
The size field in the header might not correspond to the number of records in the file if the table is public and records are added or removed from the table during dumping. Public tables updated during dump, and that one wants to verify when reading, needs at least one field of extended information for the read verification process to be reliable later.
Option
The number of objects written to the file is noted in the file footer, so file truncation can be verified even if the file was updated during dump.
The header and objects in the file are checksummed using the built-in MD5 functions. The MD5 sum of all objects is written in the file footer, so that verification while reading detects the slightest bitflip in the file data. Using this costs a fair amount of CPU time.
Whenever option
If option
Returns a list of all objects in table
Returns information about the table dumped to file by
The following items are returned:
The name of the dumped table. If the table was a
named table, a table with the same name cannot exist when the
table is loaded from file with
The ETS type of the dumped table (that is,
The protection of the dumped table (that is,
The
The number of objects in the table when the table dump
to file started. For a
The extended information written in the file footer to
allow stronger verification during table loading from file, as
specified to
A tuple
An error is returned if the file is inaccessible,
badly damaged, or not produced with
Returns a Query List
Comprehension (QLC) query handle. The
When there are only simple restrictions on the key position,
QLC uses
The table is traversed one key at a time by calling
The table is traversed one key at a time by calling
The table is traversed by calling
As for
Examples:
An explicit match specification is here used to traverse the table:
9> true = ets:insert(Tab = ets:new(t, []), [{1,a},{2,b},{3,c},{4,d}]), MS = ets:fun2ms(fun({X,Y}) when (X > 1) or (X < 5) -> {Y} end), QH1 = ets:table(Tab, [{traverse, {select, MS}}]).
An example with an implicit match specification:
10> QH2 = qlc:q([{Y} || {X,Y} <- ets:table(Tab), (X > 1) or (X < 5)]).
The latter example is equivalent to the former, which
can be verified using function
11> qlc:info(QH1) =:= qlc:info(QH2). true
Returns and removes a list of all objects with key
The specified
This function is a utility to test a
If the match specification is syntactically correct, the function
either returns
If the match specification contains errors, tuple
This is a useful debugging and test tool, especially when
writing complicated
See also:
Fills an already created/opened Dets table with the objects
in the already opened ETS table named
This function provides an efficient way to update one or more
counters, without the trouble of having to look up an object, update
the object by incrementing an element, and insert the resulting
object into the table again. The operation is guaranteed to be
This function destructively update the object with key
If a
A list of
The specified
If a default object
The function fails with reason
This function provides an efficient way to update one or more elements within an object, without the trouble of having to look up, update, and write back the entire object.
This function destructively updates the object with key
A list of
Returns
The specified
The function fails with reason
This function returns the
If the table is deleted, the