【问题标题】:Mnesia equivalent of SQL NOT INMnesia 相当于 SQL NOT IN
【发布时间】:2012-03-10 00:05:48
【问题描述】:

我有两条记录:

-record(foo, {timestamp, name}).
-record(bar, {timestamp, name}).

我想执行一个模仿以下 SQL 查询的 Mnesia 查询

SELECT f.* FROM foo f WHERE f.timestamp NOT IN ( SELECT b.timestamp FROM boo b)

什么是高效的 Mnesia 等价物?

【问题讨论】:

    标签: erlang mnesia


    【解决方案1】:

    好问题!现在,我想到了两种方法。一个我们使用qlc,另一个我们使用mnesia's own table iteration methods with accumulators。这是第一个选项:

    %% 这里我使用 'qlc',带警卫 %% 确保时间戳 %% 在给定的“foo 记录”中 %% 在表 'bar' 中不存在
    查询()-> Is_not_in_bar = fun(邮票)-> case mnesia:dirty_read({bar,Stamp}) of []->真; _ -> 假的 结尾 结束,
    Q = qlc:q([R || R Is_not_in_bar(R#foo.timestamp) == true])), Fun = fun(QH)-> qlc:e(QH) 结束, mnesia:activity(transaction,Fun,[Q],mnesia_frag)。
    另一种选择是迭代表foo,同时交叉引用表bar 中的每个时间戳。如果在bar 中找不到它,则将其添加到累计金额中。看看下面这个

    %% 这里我迭代表'foo' %% 对于我找到的每条记录, %% 我尝试交叉引用 %% 它在表'bar'中的时间戳 %% 如果没有找到,那么我补充一下 %% 'foo 记录' 进入缓冲区 %% 我积累这个缓冲区直到 %% 整个表 'foo' 已经 %% 遍历
    query_vsn2()-> 迭代器 = fun(#foo{timestamp = T} = Rec,Buffer)-> NewBuffer = case mnesia:dirty_read({bar,T}) of [] -> [记录|缓冲区]; _ -> 缓冲区 结尾, 新缓冲区 结尾, Find = fun(Loop)-> mnesia:foldl(Loop,[],foo) end, mnesia:activity(transaction,Find,[Iterator],mnesia_frag)。 我猜根据表大小、应用程序和用户偏好,这些功能中的每一个都会产生影响。但是,请尝试这两种方法,看看哪一种能很好地融入您的应用程序。好消息是这完全是一个读取工作,没有写入,所以我希望效率足够高。成功 !

    【讨论】:

    • 我使用mnesia:dirty_read/1 绕过事务管理器,这提高了吞吐量/速度并且(我没有尝试过)可以避免嵌套事务
    猜你喜欢
    • 2013-01-03
    • 2022-11-01
    • 1970-01-01
    • 2012-02-11
    • 1970-01-01
    • 2015-04-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多