Erlang - ETS 表之间的比较
Posted
技术标签:
【中文标题】Erlang - ETS 表之间的比较【英文标题】:Erlang - Comparing between ETS tables 【发布时间】:2015-10-27 05:52:11 【问题描述】:我们想知道如何有效地找到两个 ets 表之间的相互元素,我们尝试了 ETS 和 QLC 模块但不知道如何去做, 我们在 [bag] 选项上使用 ets,这意味着我们对同一个键有多个值。
我们正在寻找最快、最有效的解决方案。
【问题讨论】:
【参考方案1】:很难回答您的问题,因为我们对表格大小、内容结构、执行上下文(并行度?频率...)一无所知
您是否使用 lists:filter/2 测试了基本解决方案?
1> ets:new(t,[bag,named_table]).
t
2> ets:new(s,[bag,named_table]).
s
3> ets:insert(t,[1,a,1,b,2,c]).
true
4> ets:insert(s,[3,a,1,b,2,d]).
true
5> lists:filter(fun(X) -> lists:member(X,ets:tab2list(s)) end, ets:tab2list(t)).
[1,b]
6>
如果(我猜)你的表很大和/或它们的内容很复杂,你可以故意创建一个新的 ets set 表,其中键是表的完整记录,然后使用过滤第二个表的记录函数 ets:insert_new/2 作为谓词,创建的开销可能值得与元素的搜索相比:
6> ets:new(r,[set,named_table]).
r
7> lists:foreach(fun(X) -> ets:insert(r,X) end,ets:tab2list(s)).
ok
8> ets:tab2list(r).
[3,a,2,d,1,b]
9> lists:filter(fun(Y) -> ets:insert_new(r,Y) == false end,ets:tab2list(t)).
[1,b]
10>
我在这个例子中使用了 ets:tab2list/1 以便在 shell 中轻松地进行演示,但是可以使用任何遍历 ets 表的方法。
【讨论】:
【参考方案2】:您可以迭代一个表并为每个元素检查它是否在第二个表中。使用ets:select
可以减少被复制的数据。
例如,假设我们构建了一个下表:
1> Tab = ets:new(foo, [bag]).
2> [ets:insert(Tab, X, Y) || X <- lists:seq(1,10), Y <- lists:seq(1, 10)].
要检查表中是否有一对3, 4
,您可以这样做:
3> ets:select(Tab, [3, 4, [], [true]]).
[true]
如果这对不在表中,您将得到一个空列表:
4> ets:select(Tab, [3, 11, [], [true]]).
[]
我不能 100% 确定性能,但我认为,由于我们匹配键,因此查找将是 O(M),其中 M 是同一键下的平均项目数。
最后一步是从另一个表中获取所有内容并迭代调用ets:select
。由于您需要从第一个表中获取所有数据,ets:tab2list
可能没问题,但需要注意的是它会导致所有数据被复制。这是一个简单的例子:
5> Tab2 = ets:new(bar, [bag]),
[ets:insert(Tab2, X, Y) || X <- lists:seq(7,12), Y <- lists:seq(7, 12)].
% iterate Tab2, return only tuples which exist in Tab
6> [Element || Element <- ets:tab2list(Tab2), ets:select(Tab, [Element, [], [true]]) =:= [true]].
如果两个表都非常大,您可能需要考虑使用ets:first
、ets:next
和ets:lookup
手动迭代,以避免一次复制所有数据。
当然,最好衡量和验证哪种方法最适合您的情况。
【讨论】:
以上是关于Erlang - ETS 表之间的比较的主要内容,如果未能解决你的问题,请参考以下文章