檢視原始碼 ets (stdlib v6.2)
內建的詞組儲存。
此模組是 Erlang 內建詞組儲存 BIF 的介面。它們提供了在 Erlang 執行系統中儲存大量資料,並且能夠以固定的時間存取資料的能力。(在 ordered_set
的情況下,請見下方說明,存取時間與儲存物件數量的對數成正比。)
資料以一組動態表格的形式組織,這些表格可以儲存元組。每個表格都由一個程序建立。當程序終止時,表格會自動銷毀。每個表格都在建立時設定了存取權限。
表格分為四種不同的類型:set
、ordered_set
、bag
和 duplicate_bag
。set
或 ordered_set
表格只能有一個與每個鍵相關聯的物件。bag
或 duplicate_bag
表格可以有多個與每個鍵相關聯的物件。
類型為 set
的表格插入和查找時間是固定的,與表格大小無關。對於 bag
和 duplicate_bag
類型,時間與具有相同鍵的物件數量成正比。即使是看似不相關的鍵,也可能在尋找目標鍵時導致必須跳過線性搜尋(由於雜湊碰撞)。
警告
對於類型為
bag
和duplicate_bag
的表格,請避免插入大量具有相同鍵的物件。這會損害插入和查找效能,以及執行環境的即時特性(雜湊桶線性搜尋不會產生)。
ordered_set
表格類型使用二元搜尋樹。插入和查找時間與表格中物件數量的對數成正比。
注意
過去,一個 Erlang 節點儲存的表格數量是有限制的。現在已不再是這種情況(記憶體用量除外)。先前的預設限制約為 1400 個表格,可以透過設定環境變數
ERL_MAX_ETS_TABLES
或在啟動 Erlang 執行系統之前使用命令列選項+e
來增加。這個硬性限制已移除,但目前設定ERL_MAX_ETS_TABLES
仍然有用。它應該設定為所使用表格的最大數量的近似值,因為命名表格的內部表格是使用此值調整大小的。如果使用大量的命名表格,而且ERL_MAX_ETS_TABLES
沒有增加,則命名表格查找的效能會降低。
請注意,表格沒有自動垃圾收集。即使沒有任何程序引用表格,除非擁有者程序終止,否則它也不會自動銷毀。若要明確銷毀表格,請使用函數 delete/1
。預設擁有者是建立表格的程序。若要在程序終止時轉移表格擁有權,請使用選項 heir
或呼叫 give_away/3
。
一些實作細節
請注意比對和比較相等之間的細微差異,這可以透過表格類型 set
和 ordered_set
來示範
- 如果兩個 Erlang 詞組屬於同一類型且具有相同的值,則它們會
比對
,因此1
與1
比對,但不與1.0
比對(因為1.0
是float/0
而不是integer/0
)。 - 如果兩個 Erlang 詞組屬於同一類型且具有相同的值,或者如果兩者都是數值類型且延伸到相同的值,則它們會比較相等,因此
1
與1
和1.0
比較相等。 ordered_set
使用Erlang 詞組順序,而且integer/0
和延伸到相同值的float/0
之間不存在已定義的順序。因此,在ordered_set
表格中,鍵1
和鍵1.0
會被視為相等。
失敗
此模組中的函式會因錯誤原因而引發錯誤例外狀況
badarg
- 如果任何引數格式錯誤。badarg
- 如果表格識別碼無效。system_limit
- 修改值會導致該值無法在 VM 內部表示。例如,計數器遞增超過可表示的最大整數。system_limit
- 如果做為引數傳遞的比對規格具有過多的巢狀結構,導致呼叫程序在其上執行的排程器的排程器堆疊耗盡。排程器堆疊大小可以在啟動執行系統時設定。
並行
此模組提供一些對並行存取的有限支援。保證對單一物件的所有更新都是原子且隔離的。這表示對單一物件的更新操作要么完全成功,要么完全失敗而沒有任何影響(原子性),而且其他程序看不到更新的任何中間結果(隔離性)。一些更新多個物件的函式表示它們甚至保證整個操作的原子性和隔離性。在資料庫術語中,隔離層級可以被視為「可序列化」,就好像所有隔離的操作都嚴格地按順序一個接一個地依序執行。
表格遍歷
有不同的方式可以遍歷表格的物件。
- 單步遍歷一次一個鍵,使用
first/1
、next/2
、last/1
和prev/2
。 - 單步遍歷一次一個鍵,但使用
first_lookup/1
、next_lookup/2
、last_lookup/1
和prev_lookup/2
。當您也需要查找鍵的物件時,這更有效率。 - 使用簡單的比對模式搜尋,使用
match/1/2/3
、match_delete/2
和match_object/1/2/3
。 - 使用更強大的比對規格搜尋,使用
select/1/2/3
、select_count/2
、select_delete/2
、select_replace/2
和select_reverse/1/2/3
。 - 表格轉換,使用
tab2file/2/3
和tab2list/1
。
如果表格在遍歷期間也由並行程序更新,則沒有任何表格遍歷可以保證整個表格的一致快照。每個並行更新的物件的結果可能會被看到(或看不到),這取決於遍歷存取表格的該部分時是否發生了更新。如果真的需要,保證完整一致的表格快照的唯一方法是在整個遍歷過程中禁止並行更新。
此外,如果未以安全方式在遍歷期間插入或刪除鍵的表格上執行遍歷,可能會產生以下不良影響
- 可能會遺漏任何鍵。
- 可能會多次找到任何鍵。
- 如果刪除鍵,遍歷可能會因
badarg
例外狀況而失敗。
如果滿足以下任一條件,則表格遍歷是安全的
- 表格的類型為
ordered_set
。 - 整個表格遍歷是在一個 ETS 函數呼叫內完成的。
- 函數
safe_fixtable/2
用於在整個遍歷過程中保持表格固定。
注意
即使始終保證單一物件的存取是原子且隔離的,但是每次透過表格尋找下一個鍵的遍歷都沒有這種保證。這通常不是問題,但如果並行程序在遍歷期間插入物件,則可能會導致罕見的細微「意外」影響。例如,請考慮一個程序執行
ets:new(t, [ordered_set, named_table]), ets:insert(t, {1}), ets:insert(t, {2}), ets:insert(t, {3}),
另一個程序並行呼叫
ets:first(t)
,在極少數情況下可能會傳回2
,即使2
從未以第一個鍵的順序存在於表格中。同樣地,並行呼叫ets:next(t, 1)
可能會傳回3
,即使3
從未以緊接在1
之後的順序存在於表格中。像這樣的影響不太可能但有可能發生。如果未啟用表格選項
write_concurrency
,則發生的機率會進一步降低(如果不是消失的話)。這也可能只是ordered_set
的潛在問題,其中定義了遍歷順序。
使用 match
和 select
函數的遍歷可能不需要掃描整個表格,這取決於如何指定鍵。具有完全繫結鍵(沒有任何比對變數)的比對模式會將操作最佳化為單一鍵查找,而無需任何表格遍歷。對於 ordered_set
,部分繫結鍵會將遍歷限制為僅掃描表格的子集,這取決於詞組順序。部分繫結鍵是清單或具有完全繫結前綴的元組。範例
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"]]
比對規格
一些函數使用比對規格,match_spec
。如需簡短說明,請參閱 select/2
。如需詳細說明,請參閱 ERTS 使用者指南中的 Erlang 中的比對規格章節。
具有過多巢狀結構的比對規格會導致引發 system_limit
錯誤例外狀況。
摘要
函式
傳回節點上所有表格的列表。具名表格會以其名稱指定,未命名表格會以其表格識別符指定。
刪除整個表格 Table
。
從表格 Table
中刪除所有具有鍵 Key
的物件。即使不存在具有鍵 Key
的物件,此函式也會成功。
刪除 ETS 表格 Table
中的所有物件。保證此操作是 原子且隔離的。
從 ETS 表格中刪除確切的物件 Object
,保留具有相同鍵但其他差異的物件(對於類型 bag
很有用)。在 duplicate_bag
表格中,會刪除物件的所有實例。
讀取由 tab2file/2
或 tab2file/3
產生的檔案,並建立對應的表格 Table
。
讀取由 tab2file/2
或 tab2file/3
產生的檔案,並建立對應的表格 Table
。
傳回表格 Table
中的第一個鍵 Key
。對於 ordered_set
表格,會傳回 Erlang 項排序中的第一個鍵。對於其他表格類型,會傳回根據表格內部順序的第一個鍵。如果表格為空,則會傳回 '$end_of_table'
。
如果表格為空,則會傳回 Acc0
。此函式與 lists:foldl/3
類似。表格元素會以未指定的順序遍歷,但 ordered_set
表格除外,它們會從頭到尾遍歷。
如果表格為空,則會傳回 Acc0
。此函式與 lists:foldr/3
類似。表格元素會以未指定的順序遍歷,但 ordered_set
表格除外,它們會從尾到頭遍歷。
用已開啟的 Dets 表格 DetsTab
中的物件填滿已建立的 ETS 表格。除非被覆寫,否則 ETS 表格中現有的物件會保留。
偽函式,藉由 parse_transform
將在函式呼叫中輸入為參數的 LiteralFun
轉換為 匹配規格。所謂「文字」,是指 fun 必須以文字形式寫成函式的參數,它不能保存在變數中,而該變數又傳遞給函式。
使進程 Pid
成為表格 Table
的新擁有者。如果成功,則會將訊息 {'ETS-TRANSFER',Table,FromPid,GiftData}
送給新擁有者。
在終端機上顯示有關所有 ETS 表格的資訊。
在終端機上瀏覽表格 Table
。
以元組列表形式傳回有關表格 Table
的資訊。如果 Table
具有表格識別符的正確類型,但不參考現有的 ETS 表格,則會傳回 undefined
。如果 Table
的類型不正確,則會引發 badarg
例外狀況。
傳回與表格 Table
的 Item
相關的資訊,如果 Table
沒有參考現有的 ETS 表格,則傳回 undefined
。如果 Table
的類型不正確,或 Item
不是允許的值之一,則會引發 badarg
例外狀況。
將表格 Table
的現有物件替換為呼叫輸入函式 InitFun
建立的物件,請參閱下文。提供此函式是為了與 dets
模組相容,它不比使用 insert/2
填滿表格更有效率。
將物件或列表 ObjectOrObjects
中的所有物件插入到表格 Table
中。
與 insert/2
相同,不同之處在於,對於具有相同鍵的物件(對於 set
或 ordered_set
)或在表格中已存在鍵的物件中新增更多物件(對於 bag
和 duplicate_bag
),會傳回 false
。
檢查詞彙是否代表有效的已編譯 匹配規格。已編譯的匹配規格僅在呼叫 match_spec_compile/1
編譯它的 Erlang 節點上有效。
根據 Erlang 項排序,傳回 ordered_set
類型表格 Table
中的最後一個鍵 Key
。對於其他表格類型,此函式與 first/1
同義。如果表格為空,則會傳回 '$end_of_table'
。
傳回表格 Table
中所有具有鍵 Key
的物件的列表。
對於類型為 set
或 ordered_set
的表格 Table
,此函式會傳回具有鍵 Key
的物件的第 Pos
個元素。
對於類型為 set
或 ordered_set
的表格 Table
,此函式會傳回具有鍵 Key
的物件的第 Pos
個元素。
將表格 Table
中的物件與模式 Pattern
進行匹配。
從表格 Table
中刪除所有與模式 Pattern
匹配的物件。如需模式的說明,請參閱 match/2
。
繼續使用 match_object/3
開始的匹配。會傳回在初始 match_object/3
呼叫中指定大小的下一個區塊,以及新的 Continuation
,可用於後續呼叫此函式。
將表格 Table
中的物件與模式 Pattern
進行匹配。如需模式的說明,請參閱 match/2
。此函式會傳回與模式匹配的所有物件的列表。
與 match_object/2
類似,但只傳回有限 (Limit
) 數量的匹配物件。然後可以在後續呼叫 match_object/1
中使用詞彙 Continuation
來取得下一個匹配物件區塊。這是處理表格中物件的空間效率方式,它比使用 first/1
和 next/2
逐個物件遍歷表格更快。
將 匹配規格 轉換為內部表示法,可在後續呼叫 match_spec_run/2
中使用。內部表示法是不透明的。若要檢查已編譯匹配規格的有效性,請使用 is_compiled_ms/1
。
在詞彙列表上執行已編譯的 匹配規格 中指定的匹配。詞彙 CompiledMatchSpec
應該是呼叫 match_spec_compile/1
的結果,因此是要使用的匹配規格的內部表示法。
與 lookup/2
類似,但不傳回物件。如果表格中存在一個或多個具有鍵 Key
的元素,則會傳回 true
,否則會傳回 false
。
建立新表格,並傳回可在後續操作中使用的表格識別符。表格識別符可以傳送給其他進程,以便可以在節點內的不同進程之間共用表格。
傳回表格 Table
中鍵 Key1
之後的下一個鍵 Key2
。對於表格類型 ordered_set
,會傳回 Erlang 項次序中的下一個鍵。對於其他表格類型,則會傳回根據表格內部順序的下一個鍵。如果沒有下一個鍵存在,則會傳回 '$end_of_table'
。
根據表格類型為 ordered_set
的表格 Table
中 Erlang 項次序,傳回鍵 Key1
之前的上一個鍵 Key2
。對於其他表格類型,此函數與 next/2
同義。如果沒有上一個鍵存在,則會傳回 '$end_of_table'
。
將指定的表格 Table
重新命名為新的名稱 Name
。之後,舊名稱將無法用於存取表格。重新命名未命名的表格無效。
使用 first/1
& next/2
、match/3
& match/1
、match_object/3
& match_object/1
或 select/3
& select/1
來修正類型為 set
、bag
或 duplicate_bag
的表格,以便進行 安全遍歷。
使用 匹配規格 匹配表格 Table
中的物件。這是比 match/2
和 match_object/2
呼叫更通用的呼叫。在其最簡單的形式中,匹配規格如下:
使用 匹配規格 匹配表格 Table
中的物件。當且僅當匹配規格對物件傳回 true
時,該物件才被視為匹配並計數。對於來自匹配規格的任何其他結果,該物件都不會被視為匹配,因此不會被計數。
使用 匹配規格 匹配表格 Table
中的物件。當且僅當匹配規格對物件傳回 true
時,該物件才會從表格中移除。對於來自匹配規格的任何其他結果,該物件會被保留。這是一個比 match_delete/2
更通用的函數。
使用 匹配規格 匹配表格 Table
中的物件。對於每個匹配的物件,現有物件會被匹配規格的結果取代。
繼續以 select_reverse/3
開始的匹配。對於類型為 ordered_set
的表格,表格的遍歷會繼續到 Erlang 項次序中較早的鍵的物件。傳回的清單也包含鍵以相反順序排列的物件。對於所有其他表格類型,其行為與 select/1
完全相同。
設定表格選項。在建立表格後,唯一允許設定的選項是 heir
。呼叫程序必須是表格的所有者。
此函數主要用於偵錯目的,通常應改用 first
/next
或 last
/prev
。
將表格 Table
傾印至檔案 Filename
。
將表格 Table
傾印至檔案 Filename
。
傳回表格 Table
中所有物件的清單。
傳回使用 tab2file/2
或 tab2file/3
傾印到檔案的表格的相關資訊。
等同於 table/2
。
傳回查詢清單解析 (QLC) 查詢控制代碼。qlc
模組提供主要針對 Mnesia 的查詢語言,但 QLC 也將 ETS 表格、Dets 表格和清單識別為資料來源。呼叫 table/1,2
是使 ETS 表格 Table
可用於 QLC 的方法。
傳回並移除表格 Table
中具有鍵 Key
的所有物件的清單。
以名為 Table
的已開啟 ETS 表格中的物件,填入已建立/開啟的 Dets 表格。在插入物件之前,Dets 表格會被清空。
此函數提供一種有效的方式來更新一或多個計數器,而無需尋找物件、透過遞增元素來更新物件,以及再次將結果物件插入表格。保證此操作是原子且隔離的。
此函數提供一種有效的方式來更新物件內的一或多個元素,而無需尋找、更新和寫回整個物件。
類型
-type comp_match_spec() :: compiled_match_spec().
-opaque compiled_match_spec()
已編譯的比對規格。
-type continuation() :: '$end_of_table' | {table(), integer(), integer(), compiled_match_spec(), list(), integer()} | {table(), _, _, integer(), compiled_match_spec(), list(), integer(), integer()}.
select/1,3
、select_reverse/1,3
、match/1,3
和 match_object/1,3
使用的不透明延續。
-type match_spec() :: [{match_pattern(), [_], [_]}].
比對規格,請參閱 比對規格。
-type tab() :: table().
-type table_access() :: public | protected | private.
-type table_type() :: set | ordered_set | bag | duplicate_bag.
-opaque tid()
表格識別符,由 new/2
傳回。
函數
-spec all() -> [Table] when Table :: table().
傳回節點上所有表格的列表。具名表格會以其名稱指定,未命名表格會以其表格識別符指定。
無法保證傳回的清單中的一致性。在 ets:all()
呼叫「期間」由其他程序建立或刪除的表格,可能會或可能不會包含在清單中。只有在呼叫 ets:all()
*之前*建立/刪除的表格才能保證會包含/排除。
-spec delete(Table) -> true when Table :: table().
刪除整個表格 Table
。
從表格 Table
中刪除所有具有鍵 Key
的物件。即使不存在具有鍵 Key
的物件,此函式也會成功。
-spec delete_all_objects(Table) -> true when Table :: table().
刪除 ETS 表格 Table
中的所有物件。保證此操作是 原子且隔離的。
從 ETS 表格中刪除確切的物件 Object
,保留具有相同鍵但其他差異的物件(對於類型 bag
很有用)。在 duplicate_bag
表格中,會刪除物件的所有實例。
-spec file2tab(Filename) -> {ok, Table} | {error, Reason} when Filename :: file:name(), Table :: table(), Reason :: term().
讀取由 tab2file/2
或 tab2file/3
產生的檔案,並建立對應的表格 Table
。
-spec file2tab(Filename, Options) -> {ok, Table} | {error, Reason} when Filename :: file:name(), Table :: table(), Options :: [Option], Option :: {verify, boolean()}, Reason :: term().
讀取由 tab2file/2
或 tab2file/3
產生的檔案,並建立對應的表格 Table
。
唯一支援的選項是 {verify,boolean()}
。如果開啟驗證(透過指定 {verify,true}
),函數會使用檔案中存在的任何資訊,以判斷該資訊是否已損壞。其執行方式取決於使用 tab2file/3
寫入的 extended_info
。
如果檔案中沒有 extended_info
,且指定了 {verify,true}
,則寫入的物件數量會與傾印開始時原始表格的大小進行比較。如果表格是 public
且在表格傾印到檔案的同時有物件被新增或移除,這可能會導致驗證失敗。為了避免這個問題,請不要驗證在同時更新時傾印的檔案,或使用選項 {extended_info, [object_count]}
到 tab2file/3
,這會在檔案中擴展寫入的物件數量資訊。
如果啟用驗證,且檔案是以選項 {extended_info, [md5sum]}
寫入的,則讀取檔案的速度會較慢,並且會比其他情況消耗更多 CPU 時間。
{verify,false}
是預設值。
傳回表格 Table
中的第一個鍵 Key
。對於 ordered_set
表格,會傳回 Erlang 項排序中的第一個鍵。對於其他表格類型,會傳回根據表格內部順序的第一個鍵。如果表格為空,則會傳回 '$end_of_table'
。
若要尋找表格中的後續鍵,請使用 next/2
。
-spec first_lookup(Table) -> {Key, [Object]} | '$end_of_table' when Table :: table(), Key :: term(), Object :: tuple().
與 first/1
類似,不同之處在於它會傳回與表格中儲存的鍵一起的物件。這等同於執行 first/1
,然後執行 lookup/2
。如果表格為空,則會傳回 '$end_of_table'
。
若要尋找表格中的後續物件,請使用 next_lookup/2
。
-spec foldl(Function, Acc0, Table) -> Acc1 when Function :: fun((Element :: term(), AccIn) -> AccOut), Table :: table(), Acc0 :: term(), Acc1 :: term(), AccIn :: term(), AccOut :: term().
如果表格為空,則會傳回 Acc0
。此函式與 lists:foldl/3
類似。表格元素會以未指定的順序遍歷,但 ordered_set
表格除外,它們會從頭到尾遍歷。
如果 Function
將物件插入到表格中,或另一個程序將物件插入到表格中,這些物件可能(取決於鍵的順序)會包含在遍歷中。
-spec foldr(Function, Acc0, Table) -> Acc1 when Function :: fun((Element :: term(), AccIn) -> AccOut), Table :: table(), Acc0 :: term(), Acc1 :: term(), AccIn :: term(), AccOut :: term().
如果表格為空,則會傳回 Acc0
。此函式與 lists:foldr/3
類似。表格元素會以未指定的順序遍歷,但 ordered_set
表格除外,它們會從尾到頭遍歷。
如果 Function
將物件插入到表格中,或另一個程序將物件插入到表格中,這些物件可能(取決於鍵的順序)會包含在遍歷中。
-spec from_dets(Table, DetsTab) -> true when Table :: table(), DetsTab :: dets:tab_name().
用已開啟的 Dets 表格 DetsTab
中的物件填滿已建立的 ETS 表格。除非被覆寫,否則 ETS 表格中現有的物件會保留。
如果任何表格不存在或 Dets 表格未開啟,則會引發 badarg
例外。
-spec fun2ms(LiteralFun) -> MatchSpec when LiteralFun :: function(), MatchSpec :: match_spec().
偽函式,藉由 parse_transform
將在函式呼叫中輸入為參數的 LiteralFun
轉換為 匹配規格。所謂「文字」,是指 fun 必須以文字形式寫成函式的參數,它不能保存在變數中,而該變數又傳遞給函式。
解析轉換是在 ms_transform
模組中提供的,且原始碼必須包含 STDLIB 中的檔案 ms_transform.hrl
,此虛擬函式才能運作。若未在原始碼中包含 hrl 檔案,則會導致執行階段錯誤,而非編譯時間錯誤。最簡單的包含檔案方式是在原始碼檔案中加入 -include_lib("stdlib/include/ms_transform.hrl").
行。
fun 函數非常受限,它只能接受單一參數(要比對的物件):單一變數或 tuple。它必須使用 is_
守衛測試。在比對規格中沒有表示的語言結構(if
、case
、receive
等)是不允許的。
傳回值是產生的比對規格。
範例
1> ets:fun2ms(fun({M,N}) when N > 3 -> M end).
[{{'$1','$2'},[{'>','$2',3}],['$1']}]
可以匯入環境中的變數,因此下列程式碼可以運作
2> X=3.
3
3> ets:fun2ms(fun({M,N}) when N > X -> M end).
[{{'$1','$2'},[{'>','$2',{const,3}}],['$1']}]
匯入的變數會被比對規格 const
運算式取代,這與 Erlang fun 函數的靜態作用域一致。但是,區域或全域函數呼叫不能在 fun 函數的守衛或主體中。當然允許呼叫內建的比對規格函數。
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']}]
如範例所示,該函數也可以從 shell 中呼叫。從 shell 使用時,fun 函數必須以文字形式出現在呼叫中。
警告
如果
parse_transform
沒有應用於呼叫此虛擬函數的模組,則呼叫會在執行階段失敗(並出現badarg
)。ets
模組會匯出具有此名稱的函數,但除非在 shell 中使用該函數,否則永遠不會呼叫它。如果透過包含標頭檔ms_transform.hrl
正確應用parse_transform
,則編譯後的程式碼永遠不會呼叫該函數,而是以文字比對規格取代函數呼叫。
如需詳細資訊,請參閱 ms_transform
。
-spec give_away(Table, Pid, GiftData) -> true when Table :: table(), Pid :: pid(), GiftData :: term().
使進程 Pid
成為表格 Table
的新擁有者。如果成功,則會將訊息 {'ETS-TRANSFER',Table,FromPid,GiftData}
送給新擁有者。
程序 Pid
必須是活動的、本機的,且不能已經是表格的所有者。呼叫程序必須是表格的所有者。
請注意,此函數不會影響表格的選項 heir
。舉例來說,表格所有者可以將 heir
設定為自己,放棄表格,然後在接收者終止時取回。
-spec i() -> ok.
在終端機上顯示有關所有 ETS 表格的資訊。
-spec i(Table) -> ok when Table :: table().
在終端機上瀏覽表格 Table
。
-spec info(Table) -> InfoList | undefined when Table :: table(), InfoList :: [InfoTuple], InfoTuple :: {compressed, boolean()} | {decentralized_counters, boolean()} | {heir, pid() | none} | {id, tid()} | {keypos, pos_integer()} | {memory, non_neg_integer()} | {name, atom()} | {named_table, boolean()} | {node, node()} | {owner, pid()} | {protection, table_access()} | {size, non_neg_integer()} | {type, table_type()} | {write_concurrency, boolean()} | {read_concurrency, boolean()}.
以元組列表形式傳回有關表格 Table
的資訊。如果 Table
具有表格識別符的正確類型,但不參考現有的 ETS 表格,則會傳回 undefined
。如果 Table
的類型不正確,則會引發 badarg
例外狀況。
{compressed, boolean()}
- 表示表格是否已壓縮。{decentralized_counters, boolean()}
- 表示表格是否使用decentralized_counters
。{heir, pid() | none}
- 表格繼承者的 pid,或如果未設定繼承者,則為none
。{id,
tid()
}
- 表格識別碼。{keypos, integer() >= 1}
- 鍵的位置。{memory, integer() >= 0}
- 配置給表格的字組數。{name, atom()}
- 表格名稱。{named_table, boolean()}
- 表示表格是否已命名。{node, node()}
- 儲存表格的節點。此欄位不再有意義,因為無法從其他節點存取表格。{owner, pid()}
- 表格所有者的 pid。{protection,
access()
}
- 表格存取權限。{size, integer() >= 0}
- 插入表格的物件數量。{type,
type()
}
- 表格類型。{read_concurrency, boolean()}
- 表示表格是否使用read_concurrency
。{write_concurrency, WriteConcurrencyAlternative}
- 表示表格使用哪種write_concurrency
選項。
注意
此函數的執行時間會受到
decentralized_counters
表格選項的影響。當decentralized_counters
選項設定為true
時,執行時間會比decentralized_counters
選項設定為false
時長得多。
-spec info(Table, Item) -> Value | undefined when Table :: table(), Item :: binary | compressed | decentralized_counters | fixed | heir | id | keypos | memory | name | named_table | node | owner | protection | safe_fixed | safe_fixed_monotonic_time | size | stats | type | write_concurrency | read_concurrency, Value :: term().
傳回與表格 Table
的 Item
相關的資訊,如果 Table
沒有參考現有的 ETS 表格,則傳回 undefined
。如果 Table
的類型不正確,或 Item
不是允許的值之一,則會引發 badarg
例外狀況。
除了為 info/1
定義的 {Item,Value}
配對之外,還允許下列項目
Item=binary, Value=BinInfo
BinInfo
是包含表格所保留的二進位檔雜項資訊的清單。此Item
可能會變更或移除,恕不另行通知。在目前的實作中,BinInfo
是 tuple{BinaryId,BinarySize,BinaryRefcCount}
的清單。Item=fixed, Value=boolean()
表示表格是否被任何程序固定。
Item=safe_fixed|safe_fixed_monotonic_time, Value={FixationTime,Info}|false
如果表格使用
safe_fixtable/2
固定,則呼叫會傳回一個 tuple,其中FixationTime
是表格從未固定變為固定的最後時間。FixationTime
的格式和值取決於Item
safe_fixed
-FixationTime
對應於固定時erlang:timestamp/0
傳回的結果。請注意,當系統使用單一或多重時間扭曲模式時,這可能會產生奇怪的結果,因為safe_fixed
的使用並非時間扭曲安全。時間扭曲安全程式碼必須改用safe_fixed_monotonic_time
。safe_fixed_monotonic_time
-FixationTime
對應於固定時erlang:monotonic_time/0
傳回的結果。safe_fixed_monotonic_time
的使用是時間扭曲安全的。
Info
是一個可能為空的 tuple{Pid,RefCount}
清單,表格目前被每個程序固定一個 tuple。RefCount
是參考計數器的值,它會追蹤表格被程序固定的次數。表格固定不限於
safe_fixtable/2
。暫時性固定也可以由例如 遍歷函數 (如select
和match
) 完成。這類表格固定會在對應函數傳回之前自動釋放,但同時呼叫ets:info(T,safe_fixed|safe_fixed_monotonic_time)
可以看到它們。如果表格完全未固定,則呼叫會傳回
false
。Item=stats, Value=tuple()
傳回有關 OTP 測試套件使用的內部格式表格的內部統計資料。不適用於生產用途。
注意
當函數的第二個引數為
size
或memory
時,此函數的執行時間會受到decentralized_counters
表格選項的影響。當decentralized_counters
選項設定為true
時,執行時間會比decentralized_counters
選項設定為false
時長得多。
-spec init_table(Table, InitFun) -> true when Table :: table(), InitFun :: fun((Arg) -> Res), Arg :: read | close, Res :: end_of_input | {Objects :: [term()], InitFun} | term().
將表格 Table
的現有物件替換為呼叫輸入函式 InitFun
建立的物件,請參閱下文。提供此函式是為了與 dets
模組相容,它不比使用 insert/2
填滿表格更有效率。
以引數 read
呼叫時,會假定函數 InitFun
在沒有更多輸入時傳回 end_of_input
,或傳回 {Objects, Fun}
,其中 Objects
是物件清單,而 Fun
是新的輸入函數。任何其他值 Value
都會以錯誤 {error, {init_fun, Value}}
的形式傳回。每個輸入函數都只會呼叫一次,如果發生錯誤,則會以引數 close
呼叫最後一個函數,其回覆會被忽略。
如果表格類型為 set
,且存在多個具有指定鍵的物件,則會選擇其中一個物件。這不一定是輸入函數傳回的物件序列中具有指定鍵的最後一個物件。對於儲存在類型為 bag
的表格中的重複物件也適用。
-spec insert(Table, ObjectOrObjects) -> true when Table :: table(), ObjectOrObjects :: tuple() | [tuple()].
將物件或列表 ObjectOrObjects
中的所有物件插入到表格 Table
中。
- 如果表格類型為
set
,且插入物件的鍵符合表格中任何物件的鍵,則會取代舊物件。 - 如果表格類型為
ordered_set
,且插入物件的鍵與表格中任何物件的鍵比較相等,則會取代舊物件。 - 如果表格類型為
bag
,且物件符合表格中的任何完整物件,則不會插入該物件。 - 如果清單包含多個具有符合鍵的物件,且表格類型為
set
,則會插入其中一個物件,未定義插入哪一個。如果鍵比較相等,則表格類型ordered_set
也適用。
即使插入物件清單,也保證整個操作是原子性和隔離的。
對於 bag
和 duplicate_bag
,具有相同鍵的清單中的物件將會按照清單順序(從頭到尾)插入。也就是說,後續呼叫 lookup(T,Key)
將會按照該插入順序傳回它們。
注意
對於
bag
,在 OTP 23.0 中,上述相同鍵的插入順序被意外地還原,並在 OTP 25.3 中修復。也就是說,從 OTP 23.0 到 OTP 25.3,清單中的物件會以相反的順序插入(從尾到頭)。對於
duplicate_bag
,從 OTP 23.0 到 OTP 25.3 也存在相同的錯誤的反向插入。但是,它是不可預測的,並且可能會發生也可能不會發生。較長的清單會增加反向插入發生的機率。
-spec insert_new(Table, ObjectOrObjects) -> boolean() when Table :: table(), ObjectOrObjects :: tuple() | [tuple()].
與 insert/2
相同,不同之處在於,對於具有相同鍵的物件(對於 set
或 ordered_set
)或在表格中已存在鍵的物件中新增更多物件(對於 bag
和 duplicate_bag
),會傳回 false
。
如果 ObjectOrObjects
是一個列表,函式會先檢查每個鍵,然後才插入任何東西。除非列表中所有鍵都不存在於表格中,否則不會插入任何東西。與 insert/2
類似,整個操作保證是原子且隔離的。
檢查詞彙是否代表有效的已編譯 匹配規格。已編譯的匹配規格僅在呼叫 match_spec_compile/1
編譯它的 Erlang 節點上有效。
注意
在 STDLIB 3.4 (OTP 20.0) 之前,編譯過的匹配規範沒有外部表示形式。如果透過
binary_to_term(term_to_binary(CMS))
傳遞,或傳送到另一個節點再傳回來,結果始終會是空的二進制<<>>
。在 STDLIB 3.4 (OTP 20.0) 之後,編譯過的匹配規範具有外部表示形式,作為對原始編譯匹配規範的節點特定引用。如果透過
binary_to_term(term_to_binary(CMS))
傳遞,或傳送到另一個節點再傳回來,結果可能是有效或無效的編譯匹配規範,取決於原始編譯匹配規範是否仍然存在。
根據 Erlang 項排序,傳回 ordered_set
類型表格 Table
中的最後一個鍵 Key
。對於其他表格類型,此函式與 first/1
同義。如果表格為空,則會傳回 '$end_of_table'
。
要查找表格中前面的鍵,請使用 prev/2
。
-spec last_lookup(Table) -> {Key, [Object]} | '$end_of_table' when Table :: table(), Key :: term(), Object :: tuple().
與 last/1
類似,不同之處在於它會傳回與表格中儲存的鍵一起的物件。這等同於執行 last/1
,然後執行 lookup/2
。如果表格為空,則會傳回 '$end_of_table'
。
要查找表格中前面的物件,請使用 prev_lookup/2
。
傳回表格 Table
中所有具有鍵 Key
的物件的列表。
- 對於
set
、bag
或duplicate_bag
類型的表格,只有當指定的鍵匹配表格中物件的鍵時,才會傳回物件。 - 對於
ordered_set
類型的表格,如果指定的鍵與表格中物件的鍵比較相等,則會傳回物件。
差異與 =:=
和 ==
之間的差異相同。
舉例來說,可以在 ordered_set
中插入一個鍵為 integer/0
1
的物件,並透過使用 float/0
1.0
作為搜尋鍵的 lookup/2
,取得傳回的物件。
對於 set
或 ordered_set
類型的表格,函式會傳回空列表或包含一個元素的列表,因為不能有多個具有相同鍵的物件。對於 bag
或 duplicate_bag
類型的表格,函式會傳回任意長度的列表。
請注意,物件插入的順序會被保留;第一個以指定鍵插入的物件會是結果列表中的第一個,依此類推。另請參閱關於 列表插入順序 的說明。
-spec lookup_element(Table, Key, Pos) -> Elem when Table :: table(), Key :: term(), Pos :: pos_integer(), Elem :: term() | [term()].
對於類型為 set
或 ordered_set
的表格 Table
,此函式會傳回具有鍵 Key
的物件的第 Pos
個元素。
對於 bag
或 duplicate_bag
類型的表格,函式會傳回一個列表,其中包含每個鍵為 Key
的物件的第 Pos
個元素。
如果沒有鍵為 Key
的物件存在,函式會以原因 badarg
退出。
如果 Pos
大於元組的大小,函式會以原因 badarg
退出。
關於 set
、bag
和 duplicate_bag
與 ordered_set
之間的差異,在於 ordered_set
會在鍵比較相等時將其視為相等,而其他表格類型僅在鍵匹配時才將其視為相等,這也適用於 lookup_element/3
。
-spec lookup_element(Table, Key, Pos, Default) -> Elem when Table :: table(), Key :: term(), Pos :: pos_integer(), Default :: term(), Elem :: term() | [term()].
對於類型為 set
或 ordered_set
的表格 Table
,此函式會傳回具有鍵 Key
的物件的第 Pos
個元素。
對於 bag
或 duplicate_bag
類型的表格,函式會傳回一個列表,其中包含每個鍵為 Key
的物件的第 Pos
個元素。
如果沒有鍵為 Key
的物件存在,函式會傳回 Default
。
如果 Pos
大於任何具有匹配鍵的元組的大小,函式會以原因 badarg
退出。
關於 set
、bag
和 duplicate_bag
與 ordered_set
之間的差異,在於 ordered_set
會在鍵比較相等時將其視為相等,而其他表格類型僅在鍵匹配時才將其視為相等,這也適用於 lookup_element/4
。
-spec match(Continuation) -> {[Match], Continuation} | '$end_of_table' when Match :: [term()], Continuation :: continuation().
繼續使用 match/3
開始的匹配。會傳回在初始 match/3
呼叫中指定大小的下一個區塊,以及新的 Continuation
,可用於後續呼叫此函式。
當表格中沒有更多物件時,會傳回 '$end_of_table'
。
-spec match(Table, Pattern) -> [Match] when Table :: table(), Pattern :: match_pattern(), Match :: [term()].
將表格 Table
中的物件與模式 Pattern
進行匹配。
模式是一個可以包含的項
- 綁定部分 (Erlang 項)
'_'
,匹配任何 Erlang 項- 模式變數
'$N'
,其中N
=0,1,...
函式會傳回一個列表,其中每個匹配的物件都有一個元素,其中每個元素都是一個模式變數綁定的有序列表,例如
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'}).
[]
如果在模式中指定了鍵,則匹配非常有效率。如果未指定鍵,也就是說,如果它是變數或底線,則必須搜尋整個表格。如果表格非常大,搜尋時間可能會很長。
對於 ordered_set
類型的表格,結果的順序與 first
/next
遍歷中的順序相同。
-spec match(Table, Pattern, Limit) -> {[Match], Continuation} | '$end_of_table' when Table :: table(), Pattern :: match_pattern(), Limit :: pos_integer(), Match :: [term()], Continuation :: continuation().
與 match/2
類似,但只傳回有限 (Limit
) 數量的匹配物件。然後可以在後續呼叫 match/1
中使用詞彙 Continuation
來取得下一個匹配物件區塊。這是處理表格中物件的空間效率方式,它比使用 first/1
和 next/2
逐個物件遍歷表格更快。
如果表格為空,則會傳回 '$end_of_table'
。
使用 safe_fixtable/2
來保證後續調用 match/1
的安全遍歷。
-spec match_delete(Table, Pattern) -> true when Table :: table(), Pattern :: match_pattern().
從表格 Table
中刪除所有與模式 Pattern
匹配的物件。如需模式的說明,請參閱 match/2
。
-spec match_object(Continuation) -> {[Object], Continuation} | '$end_of_table' when Object :: tuple(), Continuation :: continuation().
繼續使用 match_object/3
開始的匹配。會傳回在初始 match_object/3
呼叫中指定大小的下一個區塊,以及新的 Continuation
,可用於後續呼叫此函式。
當表格中沒有更多物件時,會傳回 '$end_of_table'
。
-spec match_object(Table, Pattern) -> [Object] when Table :: table(), Pattern :: match_pattern(), Object :: tuple().
將表格 Table
中的物件與模式 Pattern
進行匹配。如需模式的說明,請參閱 match/2
。此函式會傳回與模式匹配的所有物件的列表。
如果在模式中指定了鍵,則匹配非常有效率。如果未指定鍵,也就是說,如果它是變數或底線,則必須搜尋整個表格。如果表格非常大,搜尋時間可能會很長。
對於 ordered_set
類型的表格,結果的順序與 first
/next
遍歷中的順序相同。
-spec match_object(Table, Pattern, Limit) -> {[Object], Continuation} | '$end_of_table' when Table :: table(), Pattern :: match_pattern(), Limit :: pos_integer(), Object :: tuple(), Continuation :: continuation().
與 match_object/2
類似,但只傳回有限 (Limit
) 數量的匹配物件。然後可以在後續呼叫 match_object/1
中使用詞彙 Continuation
來取得下一個匹配物件區塊。這是處理表格中物件的空間效率方式,它比使用 first/1
和 next/2
逐個物件遍歷表格更快。
如果表格為空,則會傳回 '$end_of_table'
。
使用 safe_fixtable/2
來保證後續調用 match_object/1
的安全遍歷。
-spec match_spec_compile(MatchSpec) -> CompiledMatchSpec when MatchSpec :: match_spec(), CompiledMatchSpec :: compiled_match_spec().
將 匹配規格 轉換為內部表示法,可在後續呼叫 match_spec_run/2
中使用。內部表示法是不透明的。若要檢查已編譯匹配規格的有效性,請使用 is_compiled_ms/1
。
如果項 MatchSpec
不代表有效的匹配規範,則會引發 badarg
例外。
注意
此函式在一般程式碼中的用途有限。它由
dets
模組用於執行dets:select/1
操作。
-spec match_spec_run(List, CompiledMatchSpec) -> list() when List :: [term()], CompiledMatchSpec :: compiled_match_spec().
在詞彙列表上執行已編譯的 匹配規格 中指定的匹配。詞彙 CompiledMatchSpec
應該是呼叫 match_spec_compile/1
的結果,因此是要使用的匹配規格的內部表示法。
匹配會在 List
中的每個元素上執行,而函式會傳回一個包含所有結果的列表。如果 List
中的元素不匹配,則不會傳回該元素的任何內容。因此,結果列表的長度等於或小於參數 List
的長度。
範例
以下兩個調用會產生相同的結果(但執行時間肯定不同)
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),
注意
此函式在一般程式碼中的用途有限。它由
dets
模組用於執行dets:select/1
操作,並由 Mnesia 在事務期間使用。
與 lookup/2
類似,但不傳回物件。如果表格中存在一個或多個具有鍵 Key
的元素,則會傳回 true
,否則會傳回 false
。
-spec new(Name, Options) -> table() when Name :: atom(), Options :: [Option], Option :: Type | Access | named_table | {keypos, Pos} | {heir, Pid :: pid(), HeirData} | {heir, none} | Tweaks, Type :: table_type(), Access :: table_access(), WriteConcurrencyAlternative :: boolean() | auto, Tweaks :: {write_concurrency, WriteConcurrencyAlternative} | {read_concurrency, boolean()} | {decentralized_counters, boolean()} | compressed, Pos :: pos_integer(), HeirData :: term().
建立新表格,並傳回可在後續操作中使用的表格識別符。表格識別符可以傳送給其他進程,以便可以在節點內的不同進程之間共用表格。
參數 Options
是一個選項列表,指定表格類型、存取權限、鍵位置以及表格是否已命名。省略的選項使用預設值。這表示不指定任何選項 ([]
) 與指定 [set, protected, {keypos,1}, {heir,none}, {write_concurrency,false}, {read_concurrency,false}, {decentralized_counters,false}]
相同。
set
- 表格是一個set
表格:一個鍵、一個物件,物件之間沒有順序。這是預設的表格類型。ordered_set
- 表格是一個ordered_set
表格:一個鍵、一個物件,以 Erlang 項順序排序,這是 < 和 > 運算符暗示的順序。這種表格類型在某些情況下具有與其他類型表格略微不同的行為。最值得注意的是,ordered_set
表格在鍵比較相等時將其視為相等,而不僅僅是在鍵匹配時。這表示對於ordered_set
表格,integer/0
1
和float/0
1.0
被視為相等。這也表示如果float/0
和integer/0
混合在表格的鍵中,則用於查找元素的鍵不一定匹配傳回元素中的鍵。bag
- 表格是一個bag
表格,可以有多個物件,但每個鍵只能有一個物件的實例。duplicate_bag
- 表格是一個duplicate_bag
表格,可以有多個物件,包括每個鍵的同一個物件的多個副本。public
- 任何進程都可以讀取或寫入表格。protected
- 擁有者進程可以讀取和寫入表格。其他進程只能讀取表格。這是存取權限的預設設定。private
- 只有擁有者進程可以讀取或寫入表格。named_table
- 如果存在此選項,則表格會在Name
下註冊,然後可以在後續操作中使用該名稱來代替表格識別碼。函式也會傳回
Name
而不是表格識別碼。若要取得具名表格的表格識別碼,請使用whereis/1
。{keypos,Pos}
- 指定要使用儲存元組中的哪個元素作為鍵。預設情況下,它是第一個元素,也就是Pos=1
。但是,這並不總是適當的。特別是,如果我們想在表格中儲存 Erlang 記錄,我們不希望第一個元素是鍵。請注意,儲存在表格中的任何元組都必須至少有
Pos
個元素。{heir,Pid,HeirData} | {heir,none}
- 將一個進程設定為繼承者。如果擁有者終止,繼承者會繼承表格。當這種情況發生時,訊息{'ETS-TRANSFER',tid(),FromPid,HeirData}
會傳送給繼承者。繼承者必須是本地進程。預設繼承者是none
,它會在擁有者終止時銷毀表格。{write_concurrency,WriteConcurrencyAlternative}
- 效能調整。預設值為false
,在這種情況下,修改(寫入)表格的操作會取得獨佔存取權,阻止對同一表格的任何並行存取,直到完成為止。如果設定為true
,則會針對並行寫入存取優化表格。同一表格的不同物件可以由並行進程修改(和讀取)。這在一定程度上是以犧牲記憶體消耗以及循序存取和並行讀取的效能為代價來實現的。對於
write_concurrency
選項,auto
替代方案類似於true
選項,但會根據表格的使用方式在執行期間自動調整同步的粒度。當使用 Erlang/OTP 25 或更高版本時,建議使用此write_concurrency
選項,因為它在大多數情況下表現良好。write_concurrency
選項可以與read_concurrency
和decentralized_counters
選項結合使用。當大型並發讀取爆發和大型並發寫入爆發很常見時,您通常會想要將write_concurrency
與read_concurrency
結合使用;如需更多資訊,請參閱選項read_concurrency
。將write_concurrency
選項與decentralized_counters
選項結合幾乎總是個好主意。請注意,此選項不會變更關於原子性和隔離性的任何保證。對於多個物件做出此類承諾的函數(例如
insert/2
)從此選項中獲益較少(或沒有獲益)。當未使用
write_concurrency
選項的true
替代方案時,write_concurrency
和read_concurrency
所造成的記憶體消耗對於set
、bag
和duplicate_bag
而言是每個表格的恆定開銷。對於所有使用auto
替代方案的表格,以及使用true
替代方案的ordered_set
表格,記憶體開銷取決於執行期間偵測到的實際並發量。當write_concurrency
和read_concurrency
結合使用時,記憶體開銷可能會特別大。注意
在 stdlib-3.7 (OTP-22.0) 之前,
write_concurrency
對ordered_set
沒有影響。注意
write_concurrency
選項的auto
替代方案僅在 OTP-25.0 及更高版本中可用。{read_concurrency,boolean()}
(自 OTP R14B 起)
效能調整。預設值為false
。當設定為true
時,表格會針對並發讀取操作進行最佳化。當啟用此選項時,讀取操作會變得便宜許多;尤其是在具有多個實體處理器的系統上。但是,在讀取和寫入操作之間切換會變得更加昂貴。當並發讀取操作比寫入操作頻繁得多,或者當並發讀取和寫入以大型讀取和寫入爆發形式出現時(也就是說,許多讀取操作不會被寫入操作中斷,而許多寫入操作不會被讀取操作中斷),您通常會想要啟用此選項。
當常見的存取模式是重複交錯幾個讀取操作和幾個寫入操作時,您通常不會想要啟用此選項。在這種情況下,啟用此選項會導致效能下降。
選項
read_concurrency
可以與選項write_concurrency
結合使用。當大型並發讀取爆發和大型並發寫入爆發很常見時,您通常會想要將這些選項結合使用。{decentralized_counters,boolean()}
(自 OTP 23.0 起)
效能調整。對於所有將write_concurrency
選項設定為auto
的表格,預設值為true
。對於ordered_set
類型的表格,當write_concurrency
選項設定為true
時,此選項的預設值也為 true。對於所有其他組態,此選項的預設值為false
。如果將write_concurrency
選項設定為false
,則此選項無效。當此選項設定為
true
時,表格會針對頻繁並發呼叫修改表格大小和/或其記憶體消耗的操作(例如insert/2
和delete/2
)進行最佳化。缺點是,當開啟decentralized_counters
選項時,呼叫info/1
和info/2
並使用size
或memory
作為第二個引數可能會變得慢很多。當啟用此選項時,表格大小和記憶體消耗的計數器會分散在數個快取行中,而排程執行緒會對應到其中一個快取行。
erl
選項+dcg
可用來控制計數器分散的快取行數量。compressed
(自 OTP R14B01 起)
如果存在此選項,則表格資料會以更精簡的格式儲存,以消耗更少的記憶體。但是,它會使表格操作變慢。尤其是需要檢查整個物件的操作,例如match
和select
,會變得慢很多。索引鍵元素不會壓縮。
-spec next(Table, Key1) -> Key2 | '$end_of_table' when Table :: table(), Key1 :: term(), Key2 :: term().
傳回表格 Table
中鍵 Key1
之後的下一個鍵 Key2
。對於表格類型 ordered_set
,會傳回 Erlang 項次序中的下一個鍵。對於其他表格類型,則會傳回根據表格內部順序的下一個鍵。如果沒有下一個鍵存在,則會傳回 '$end_of_table'
。
若要尋找表格中的第一個索引鍵,請使用 first/1
。
除非使用 safe_fixtable/2
固定 set
、bag
或 duplicate_bag
類型的表格,否則如果表格中不再存在 Key1
,則呼叫 next/2
會失敗。對於表格類型 ordered_set
,此函數始終以詞彙順序傳回 Key1
之後的下一個索引鍵,無論表格中是否曾經存在 Key1
。
-spec next_lookup(Table, Key1) -> {Key2, [Object]} | '$end_of_table' when Table :: table(), Key1 :: term(), Key2 :: term(), Object :: tuple().
與 next/2
類似,不同之處在於它會傳回儲存在表格中的物件及其鍵。這等同於先執行 next/2
,再執行 lookup/2
。如果沒有下一個鍵存在,則會傳回 '$end_of_table'
。
它可以在遍歷期間與 next/2
交錯。
-spec prev(Table, Key1) -> Key2 | '$end_of_table' when Table :: table(), Key1 :: term(), Key2 :: term().
根據表格類型為 ordered_set
的表格 Table
中 Erlang 項次序,傳回鍵 Key1
之前的上一個鍵 Key2
。對於其他表格類型,此函數與 next/2
同義。如果沒有上一個鍵存在,則會傳回 '$end_of_table'
。
若要尋找 ordered_set
表格中的最後一個索引鍵,請使用 last/1
。
-spec prev_lookup(Table, Key1) -> {Key2, [Object]} | '$end_of_table' when Table :: table(), Key1 :: term(), Key2 :: term(), Object :: tuple().
與 prev/2
類似,不同之處在於它會傳回儲存在表格中的物件及其鍵。這等同於先執行 prev/2
,再執行 lookup/2
。如果沒有上一個鍵存在,則會傳回 '$end_of_table'
。
它可以在遍歷期間與 prev/2
交錯。
將指定的表格 Table
重新命名為新的名稱 Name
。之後,舊名稱將無法用於存取表格。重新命名未命名的表格無效。
-spec repair_continuation(Continuation, MatchSpec) -> Continuation when Continuation :: continuation(), MatchSpec :: match_spec().
還原由 select/3
或 select/1
傳回的不透明 continuation,如果 continuation 已通過外部項格式(已在節點之間傳送或儲存在磁碟上)。
此函數的原因是,繼續項包含已編譯的匹配規範,因此如果轉換為外部項格式,則可能會失效。假設原始匹配規範保持不變,則可以還原繼續項,這表示它可以在後續的 select/1
呼叫中再次使用,即使它已儲存在磁碟或另一個節點上。
範例
下列呼叫序列可能會失敗
T=ets:new(x,[]),
...
MS = ets:fun2ms(fun({N,_}=A) when (N rem 10) =:= 0 -> A end),
{_,C} = ets:select(T, MS, 10),
MaybeBroken = binary_to_term(term_to_binary(C)),
ets:select(MaybeBroken).
以下序列有效,因為呼叫 repair_continuation/2
會重新建立 MaybeBroken
繼續項。
T=ets:new(x,[]),
...
MS = ets:fun2ms(fun({N,_}=A) when (N rem 10) =:= 0 -> A end),
{_,C} = ets:select(T,MS,10),
MaybeBroken = binary_to_term(term_to_binary(C)),
ets:select(ets:repair_continuation(MaybeBroken,MS)).
注意
此函數在應用程式程式碼中很少需要。Mnesia 使用它來提供分散式的
select/3
和select/1
序列。一般應用程式會使用 Mnesia 或避免將繼續項轉換為外部格式。從外部格式重新建立時,已編譯的匹配規範的實際行為已變更,並且在未來版本中可能會變更,但此介面仍保持向後相容性。請參閱
is_compiled_ms/1
。
使用 first/1
& next/2
、match/3
& match/1
、match_object/3
& match_object/1
或 select/3
& select/1
來修正類型為 set
、bag
或 duplicate_bag
的表格,以便進行 安全遍歷。
處理序會呼叫 safe_fixtable(Table, true)
來固定表格。表格會保持固定,直到處理序呼叫 safe_fixtable(Table, false)
釋放它,或直到處理序終止。
如果許多處理序固定表格,則表格會保持固定,直到所有處理序都已釋放它(或終止)。每個處理序都會保留一個參考計數器,而 N 個連續的固定需要 N 個釋放才能釋放表格。
當表格固定時,保證即使在遍歷期間移除索引鍵,一連串的 first/1
和 next/2
呼叫也會成功。在遍歷期間插入或刪除之物件的索引鍵可能會或可能不會由 next/2
傳回,具體取決於表格中索引鍵的順序以及呼叫 next/2
時是否存在索引鍵。
範例
clean_all_with_value(Table,X) ->
safe_fixtable(Table,true),
clean_all_with_value(Table,X,ets:first(Table)),
safe_fixtable(Table,false).
clean_all_with_value(Table,X,'$end_of_table') ->
true;
clean_all_with_value(Table,X,Key) ->
case ets:lookup(Table,Key) of
[{Key,X}] ->
ets:delete(Table,Key);
_ ->
true
end,
clean_all_with_value(Table,X,ets:next(Table,Key)).
請注意,在釋放固定表格之前,不會從固定表格中釋放已刪除的物件。如果處理序固定表格但永遠不釋放它,則永遠不會釋放已刪除物件使用的記憶體。表格上的操作效能也會大幅降低。
若要擷取有關哪些處理序已固定哪些表格的資訊,請使用 info(Table, safe_fixed_monotonic_time)
。具有許多固定表格處理序的系統可能需要一個監視器,以便在表格固定太久時發出警報。
請注意,對於表格類型 ordered_set
和由單一 ETS 函數呼叫(例如 select/2
)完成的遍歷,不需要 safe_fixtable/2
。
-spec select(Continuation) -> {[Match], Continuation} | '$end_of_table' when Match :: term(), Continuation :: continuation().
繼續以 select/3
開始的匹配。傳回初始 select/3
呼叫中指定大小的下一個區塊,以及新的 Continuation
,可用於後續對此函數的呼叫。
當表格中沒有更多物件時,會傳回 '$end_of_table'
。
-spec select(Table, MatchSpec) -> [Match] when Table :: table(), MatchSpec :: match_spec(), Match :: term().
使用 匹配規格 匹配表格 Table
中的物件。這是比 match/2
和 match_object/2
呼叫更通用的呼叫。在其最簡單的形式中,匹配規格如下:
MatchSpec = [MatchFunction]
MatchFunction = {MatchHead, [Guard], [Result]}
MatchHead = "Pattern as in ets:match"
Guard = {"Guardtest name", ...}
Result = "Term construct"
這表示匹配規範始終是一個或多個 Tuple(Arity 為 3)的清單。Tuple 的第一個元素是要成為 match/2
中所述的模式。Tuple 的第二個元素是要成為 0 個或多個保護測試的清單(如下所述)。Tuple 的第三個元素是要成為包含要傳回值之描述的清單。在幾乎所有正常情況下,清單都包含一個完全描述每個物件要傳回值的項目。
傳回值是使用在 MatchHead
中繫結的「匹配變數」或使用特殊的匹配變數 '$_'
(整個匹配物件)和 '$$'
(清單中的所有匹配變數)所建構,因此下列 match/2
運算式
ets:match(Table,{'$1','$2','$3'})
與下列程式碼完全相同
ets:select(Table,[{{'$1','$2','$3'},[],['$$']}])
而下列 match_object/2
呼叫
ets:match_object(Table,{'$1','$2','$1'})
與下列程式碼完全相同
ets:select(Table,[{{'$1','$2','$1'},[],['$_']}])
可以在 Result
部分中建構複合項目,方法是簡單地撰寫一個清單,因此下列程式碼
ets:select(Table,[{{'$1','$2','$3'},[],['$$']}])
會產生與下列程式碼相同的輸出
ets:select(Table,[{{'$1','$2','$3'},[],[['$1','$2','$3']]}])
也就是說,符合條件的變數會以列表形式回傳。如果要建構元組,則必須寫一個 arity 為 1 的元組,其中唯一的元素是想要建構的元組(因為一般的元組可能會被誤認為 Guard
)。
因此,以下呼叫:
ets:select(Table,[{{'$1','$2','$1'},[],['$_']}])
會產生與下列程式碼相同的輸出
ets:select(Table,[{{'$1','$2','$1'},[],[{{'$1','$2','$3'}}]}])
此語法等同於 Runtime_Tools 中 dbg
模組的追蹤模式所使用的語法。
Guard
會被建構成元組,其中第一個元素是測試名稱,其餘元素是測試參數。要檢查綁定到匹配變數 '$1'
的元素是否為特定類型(例如列表),可以將測試寫成 {is_list, '$1'}
。如果測試失敗,則表格中的物件不匹配,並嘗試下一個 MatchFunction
(如果有)。Erlang 中大多數的 guard 測試都可以使用,但僅允許使用帶有 is_
前綴的新版本(is_float
、is_atom
等)。
Guard
區段也可以包含邏輯和算術運算,其語法與 guard 測試相同(前綴表示法),因此在 Erlang 中寫成的以下 guard 測試:
is_integer(X), is_integer(Y), X + Y < 4711
會表示成如下形式(X
替換為 '$1'
,Y
替換為 '$2'
):
[{is_integer, '$1'}, {is_integer, '$2'}, {'<', {'+', '$1', '$2'}, 4711}]
對於類型為 ordered_set
的表格,物件會按照 first
/next
遍歷的相同順序被訪問。這表示匹配規範會針對具有 first
/next
順序鍵的物件執行,而對應的結果列表也按照該執行順序排列。
-spec select(Table, MatchSpec, Limit) -> {[Match], Continuation} | '$end_of_table' when Table :: table(), MatchSpec :: match_spec(), Limit :: pos_integer(), Match :: term(), Continuation :: continuation().
與 select/2
的功能類似,但只傳回有限 (Limit
) 數量的匹配物件。然後,可以在後續對 select/1
的呼叫中使用項 Continuation
,以取得下一個匹配物件的區塊。這是一種在表格中處理物件的節省空間的方式,它仍然比使用 first/1
和 next/2
逐個遍歷表格物件更快。
如果表格為空,則會傳回 '$end_of_table'
。
使用 safe_fixtable/2
來保證後續呼叫 select/1
時的安全遍歷。
-spec select_count(Table, MatchSpec) -> NumMatched when Table :: table(), MatchSpec :: match_spec(), NumMatched :: non_neg_integer().
使用 匹配規格 匹配表格 Table
中的物件。當且僅當匹配規格對物件傳回 true
時,該物件才被視為匹配並計數。對於來自匹配規格的任何其他結果,該物件都不會被視為匹配,因此不會被計數。
此函數會回傳符合條件的物件數量。
-spec select_delete(Table, MatchSpec) -> NumDeleted when Table :: table(), MatchSpec :: match_spec(), NumDeleted :: non_neg_integer().
使用 匹配規格 匹配表格 Table
中的物件。當且僅當匹配規格對物件傳回 true
時,該物件才會從表格中移除。對於來自匹配規格的任何其他結果,該物件會被保留。這是一個比 match_delete/2
更通用的函數。
此函數會回傳從表格中刪除的物件數量。
注意
如果物件要被刪除,則匹配規範必須回傳原子
true
。任何其他回傳值都不會刪除物件。因此,不能使用相同的匹配規範來查找和刪除元素。
-spec select_replace(Table, MatchSpec) -> NumReplaced when Table :: table(), MatchSpec :: match_spec(), NumReplaced :: non_neg_integer().
使用 匹配規格 匹配表格 Table
中的物件。對於每個匹配的物件,現有物件會被匹配規格的結果取代。
針對每個個別物件的匹配和取代操作保證是原子且隔離的。如同其他所有 select 函式,select_replace
表格遍歷整體而言不提供此類保證。
必須保證匹配規範能保留任何匹配物件的鍵。否則,select_replace
會失敗並出現 badarg
,且不會更新任何物件。
目前,由於效能和語意限制,尚不支援類型為 bag
的表格。
此函數會回傳被取代的物件總數。
範例
針對第二個位置為列表的所有 2 元組,將原子 'marker'
添加到列表的開頭。
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]}]
通用的單一物件比較並交換操作
[Old] = ets:lookup(T, Key),
New = update_object(Old),
Success = (1 =:= ets:select_replace(T, [{Old, [], [{const, New}]}])),
-spec select_reverse(Continuation) -> {[Match], Continuation} | '$end_of_table' when Continuation :: continuation(), Match :: term().
繼續以 select_reverse/3
開始的匹配。對於類型為 ordered_set
的表格,表格的遍歷會繼續到 Erlang 項次序中較早的鍵的物件。傳回的清單也包含鍵以相反順序排列的物件。對於所有其他表格類型,其行為與 select/1
完全相同。
範例
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).
...
-spec select_reverse(Table, MatchSpec) -> [Match] when Table :: table(), MatchSpec :: match_spec(), Match :: term().
與 select/2
的功能類似,但對於表格類型 ordered_set
,會以相反的順序傳回清單。對於所有其他表格類型,其傳回值與 select/2
的傳回值相同。
-spec select_reverse(Table, MatchSpec, Limit) -> {[Match], Continuation} | '$end_of_table' when Table :: table(), MatchSpec :: match_spec(), Limit :: pos_integer(), Match :: term(), Continuation :: continuation().
與 select/3
的功能類似,但對於表格類型 ordered_set
,遍歷會從 Erlang 項次序中的最後一個物件開始,並移至第一個物件。對於所有其他表格類型,其傳回值與 select/3
的傳回值相同。
請注意,這不等同於反轉 select/3
呼叫的結果列表,因為結果列表不僅反轉,還包含表格中最後 Limit
個匹配的物件,而不是第一個。
-spec setopts(Table, Opts) -> true when Table :: table(), Opts :: Opt | [Opt], Opt :: {heir, pid(), HeirData} | {heir, none}, HeirData :: term().
設定表格選項。在建立表格後,唯一允許設定的選項是 heir
。呼叫程序必須是表格的所有者。
-spec slot(Table, I) -> [Object] | '$end_of_table' when Table :: table(), I :: non_neg_integer(), Object :: tuple().
此函數主要用於偵錯目的,通常應改用 first
/next
或 last
/prev
。
回傳表格 Table
中 slot I
的所有物件。可以透過重複呼叫此函數來遍歷表格,從第一個 slot I=0
開始,並在回傳 '$end_of_table'
時結束。如果引數 I
超出範圍,則函數會因原因 badarg
而失敗。
除非使用 safe_fixtable/2
保護類型為 set
、bag
或 duplicate_bag
的表格,否則如果同時更新表格,則遍歷可能會失敗。對於表格類型 ordered_set
,此函數會回傳一個列表,其中包含依 Erlang 項順序排列的物件 I
。
-spec tab2file(Table, Filename) -> ok | {error, Reason} when Table :: table(), Filename :: file:name(), Reason :: term().
將表格 Table
傾印至檔案 Filename
。
-spec tab2file(Table, Filename, Options) -> ok | {error, Reason} when Table :: table(), Filename :: file:name(), Options :: [Option], Option :: {extended_info, [ExtInfo]} | {sync, boolean()}, ExtInfo :: md5sum | object_count, Reason :: term().
將表格 Table
傾印至檔案 Filename
。
在傾印表格時,會將表格的一些資訊傾印到傾印開頭的標頭。此資訊包含有關表格類型、名稱、保護、大小、版本,以及是否為具名表格的資料。它還包含有關新增到檔案的擴充資訊的注意事項,這可以是檔案中物件的計數,或是檔案中標頭和記錄的 MD5 總和。
如果表格是公用的,且在傾印期間新增或移除記錄,則標頭中的大小欄位可能與檔案中的記錄數不符。在傾印期間更新的公用表格,以及想要在讀取時驗證的公用表格,至少需要一個擴充資訊欄位,以使後續的讀取驗證過程可靠。
選項 extended_info
指定要將哪些額外資訊寫入表格傾印。
object_count
- 寫入檔案的物件數會在檔案頁尾中註明,因此即使檔案在傾印期間被更新,也可以驗證檔案截斷。md5sum
- 檔案中的標頭和物件會使用內建的 MD5 函式進行檢查。所有物件的 MD5 總和會寫在檔案頁尾中,以便在讀取時驗證,並偵測檔案資料中任何最輕微的位元翻轉。使用此選項會耗費相當多的 CPU 時間。
每當使用選項 extended_info
時,都會產生一個在 STDLIB 1.15.1 之前的 ETS 版本無法讀取的檔案。
如果選項 sync
設定為 true
,則會確保檔案內容在 tab2file
回傳之前寫入磁碟。預設為 {sync, false}
。
傳回表格 Table
中所有物件的清單。
-spec tabfile_info(Filename) -> {ok, TableInfo} | {error, Reason} when Filename :: file:name(), TableInfo :: [InfoItem], InfoItem :: {name, atom()} | {type, Type} | {protection, Protection} | {named_table, boolean()} | {keypos, non_neg_integer()} | {size, non_neg_integer()} | {extended_info, [ExtInfo]} | {version, {Major :: non_neg_integer(), Minor :: non_neg_integer()}}, ExtInfo :: md5sum | object_count, Type :: bag | duplicate_bag | ordered_set | set, Protection :: private | protected | public, Reason :: term().
傳回使用 tab2file/2
或 tab2file/3
傾印到檔案的表格的相關資訊。
會回傳以下項目:
name
- 傾印表格的名稱。如果表格是具名表格,則在從檔案中使用file2tab/2
載入表格時,不能存在同名的表格。如果表格不是以具名表格形式儲存,則此欄位在從檔案載入表格時沒有任何意義。type
- 傾印表格的 ETS 類型(即set
、bag
、duplicate_bag
或ordered_set
)。再次載入表格時會使用此類型。protection
- 傾印表格的保護(即private
、protected
或public
)。從檔案載入的表格會獲得相同的保護。named_table
- 如果表格在傾印到檔案時是具名表格,則為true
,否則為false
。請注意,從檔案載入具名表格時,系統中不能存在同名的表格。keypos
- 傾印到檔案的表格的keypos
,再次載入表格時會使用它。size
- 表格開始傾印到檔案時,表格中的物件數量。對於public
表格,此數字不需要與儲存到檔案的物件數對應,因為在表格傾印期間,其他程序可能已新增或刪除物件。extended_info
- 寫在檔案頁尾中的擴充資訊,以便在從檔案載入表格期間進行更強的驗證,如tab2file/3
中所指定。請注意,此函數只會告知存在哪些資訊,而不是檔案頁尾中的值。該值是包含一個或多個原子object_count
和md5sum
的列表。version
- 包含 ETS 表格傾印檔案格式的主要和次要版本之元組{Major,Minor}
。此版本欄位從 STDLIB 1.5.1 開始新增。使用較舊版本傾印的檔案在此欄位中回傳{0,0}
。
如果檔案無法存取、嚴重損壞或不是使用 tab2file/2
或 tab2file/3
產生,則會回傳錯誤。
-spec table(Table) -> QueryHandle when Table :: table(), QueryHandle :: qlc:query_handle().
等同於 table/2
。
-spec table(Table, Options) -> QueryHandle when Table :: table(), QueryHandle :: qlc:query_handle(), Options :: [Option] | Option, Option :: {n_objects, NObjects} | {traverse, TraverseMethod}, NObjects :: default | pos_integer(), TraverseMethod :: first_next | last_prev | select | {select, MatchSpec :: match_spec()}.
傳回查詢清單解析 (QLC) 查詢控制代碼。qlc
模組提供主要針對 Mnesia 的查詢語言,但 QLC 也將 ETS 表格、Dets 表格和清單識別為資料來源。呼叫 table/1,2
是使 ETS 表格 Table
可用於 QLC 的方法。
當對鍵位置只有簡單的限制時,QLC 會使用 lookup/2
來查找鍵。當無法這樣做時,會遍歷整個表格。選項 traverse
決定如何執行此操作。
select
- 透過呼叫select/3
和select/1
來遍歷表格。選項n_objects
決定回傳的物件數量(select/3
的第三個引數);預設為一次回傳100
個物件。QLC 會組裝匹配規範(select/3
的第二個引數):簡單的篩選會轉換為等效的匹配規範,而更複雜的篩選則必須應用到select/3
回傳的所有物件,並給定一個匹配所有物件的匹配規範。{select, MatchSpec}
- 如同select
,透過呼叫select/3
和select/1
來遍歷表格。不同之處在於匹配規範是明確指定的。這是如何陳述 QLC 提供的語法中不容易表達的匹配規範。
範例
此處使用明確的匹配規範來遍歷表格:
9> true = ets:insert(Table = 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(Table, [{traverse, {select, MS}}]).
一個使用隱含匹配規範的範例:
10> QH2 = qlc:q([{Y} || {X,Y} <- ets:table(Table), (X > 1) or (X < 5)]).
後者範例等同於前者,可以使用函數 qlc:info/1
驗證。
11> qlc:info(QH1) =:= qlc:info(QH2).
true
qlc:info/1
回傳關於查詢控制代碼的資訊,在此情況下,會針對這兩個查詢控制代碼回傳相同的資訊。
傳回並移除表格 Table
中具有鍵 Key
的所有物件的清單。
指定的 Key
會被用來識別物件,在 ordered_set
表格中是透過比較相等物件的鍵來識別,在其他類型的表格中則是透過匹配來識別(關於差異的詳細資訊,請參閱 lookup/2
和 new/2
)。
-spec test_ms(Tuple, MatchSpec) -> {ok, Result} | {error, Errors} when Tuple :: tuple(), MatchSpec :: match_spec(), Result :: term(), Errors :: [{warning | error, string()}].
此函數是一個實用程式,用於測試對 select/2
的呼叫中使用的 匹配規格。此函數會測試 MatchSpec
的「語法」正確性,並針對物件 Tuple
執行匹配規格。
如果匹配規格語法正確,函數會回傳 {ok,Result}
,其中 Result
會是實際調用 select/2
時的結果,如果匹配規格不符合物件 Tuple
,則會回傳 false
。
如果匹配規格包含錯誤,則會回傳元組 {error, Errors}
,其中 Errors
是一個列表,包含關於匹配規格錯誤的自然語言描述。
這是一個有用的除錯和測試工具,尤其是在編寫複雜的 select/2
調用時。
另請參閱:erlang:match_spec_test/3
。
-spec to_dets(Table, DetsTab) -> DetsTab when Table :: table(), DetsTab :: dets:tab_name().
以名為 Table
的已開啟 ETS 表格中的物件,填入已建立/開啟的 Dets 表格。在插入物件之前,Dets 表格會被清空。
-spec update_counter(Table, Key, UpdateOp | [UpdateOp] | Incr) -> Result | [Result] when Table :: table(), Key :: term(), UpdateOp :: {Pos, Incr} | {Pos, Incr, Threshold, SetValue}, Pos :: integer(), Incr :: integer(), Threshold :: integer(), SetValue :: integer(), Result :: integer().
等同於 update_counter/4
。
-spec update_counter(Table, Key, UpdateOp | Incr | [UpdateOp], Default) -> Result | [Result] when Table :: table(), Key :: term(), UpdateOp :: {Pos, Incr} | {Pos, Incr, Threshold, SetValue}, Pos :: integer(), Incr :: integer(), Threshold :: integer(), SetValue :: integer(), Result :: integer(), Default :: tuple().
此函數提供一種有效的方式來更新一或多個計數器,而無需尋找物件、透過遞增元素來更新物件,以及再次將結果物件插入表格。保證此操作是原子且隔離的。
此函數會破壞性地更新表格 Table
中鍵為 Key
的物件,方法是將 Incr
加到位置 Pos
的元素上。傳回新的計數器值。如果未指定位置,則會更新緊接在鍵之後的元素 (<keypos>+1
)。
如果指定了 Threshold
,則在發生以下情況時,計數器會重置為值 SetValue
Incr
不是負數 (>= 0
) 且結果會大於 (>
)Threshold
。Incr
是負數 (< 0
) 且結果會小於 (<
)Threshold
。
可以提供 UpdateOp
的列表,以便在物件內執行多個更新操作。這些操作會按照列表中指定的順序執行。如果同一個計數器位置在列表中出現多次,則對應的計數器會因此被更新多次,每次都基於先前的結果。傳回值是一個列表,包含每次更新操作的新計數器值,其順序與操作列表中的順序相同。如果指定一個空列表,則不會更新任何內容,並傳回一個空列表。如果函數失敗,則不會進行任何更新。
指定的 Key
用於識別物件,方法是匹配 set
表格中物件的鍵,或在 ordered_set
表格中比較等於物件的鍵(關於差異的詳細資訊,請參閱 lookup/2
和 new/2
)。
如果指定了預設物件 Default
,則當表格中缺少鍵時,它會被用作要更新的物件。鍵位置上的值會被忽略,並被正確的鍵值取代。傳回值如同未使用預設物件一樣,即一個單一的更新元素或一個列表。
在以下情況下,函數會因 badarg
原因而失敗
- 表格類型不是
set
或ordered_set
。 - 不存在具有正確鍵的物件,且沒有提供預設物件。
- 物件的元數不正確。
- 預設物件的元數小於
<keypos>
。 - 預設物件中任何被更新的欄位都不是整數。
- 要更新的元素不是整數。
- 要更新的元素同時也是鍵。
Pos
、Incr
、Threshold
或SetValue
中的任何一個都不是整數。
-spec update_element(Table, Key, ElementSpec) -> boolean() when Table :: table(), Key :: term(), ElementSpec :: {Pos, Value} | [{Pos, Value}], Pos :: pos_integer(), Value :: term().
等同於 update_element/4
。
-spec update_element(Table, Key, ElementSpec, Default) -> true when Table :: table(), Key :: term(), ElementSpec :: {Pos, Value} | [{Pos, Value}], Pos :: pos_integer(), Value :: term(), Default :: tuple().
此函數提供一種有效的方式來更新物件內的一或多個元素,而無需尋找、更新和寫回整個物件。
此函數會破壞性地更新表格 Table
中鍵為 Key
的物件。位置 Pos
的元素會被賦予值 Value
。
可以提供 {Pos,Value}
的列表,以便在同一個物件內更新多個元素。如果同一個位置在列表中出現多次,則會寫入列表中的最後一個值。如果列表為空或函數失敗,則不會進行任何更新。該函數也是原子的,也就是說,其他進程永遠看不到任何中間結果。
如果找到鍵為 Key
的物件,則返回 true
,否則返回 false
。
指定的 Key
用於識別物件,方法是匹配 set
表格中物件的鍵,或在 ordered_set
表格中比較等於物件的鍵(關於差異的詳細資訊,請參閱 lookup/2
和 new/2
)。
如果指定了預設物件 Default
,則當表格中缺少鍵時,它會被用作要更新的物件。鍵位置上的值會被忽略,並被正確的鍵值取代。
在以下情況下,函數會因 badarg
原因而失敗
- 表格類型不是
set
或ordered_set
。 Pos
< 1.Pos
> 物件元數。- 預設物件的元數小於
<keypos>
。 - 要更新的元素同時也是鍵。
此函數會傳回由 TableName
識別的具名表格的 tid/0
,如果不存在此表格,則傳回 undefined
。在所有操作中,都可以使用 tid/0
來代替表格名稱,這會稍微快一點,因為不必在每次呼叫時都解析名稱。
如果表格被刪除,即使使用相同的名稱建立另一個具名表格,tid/0
也會失效。