【问题标题】:Mnesia: how to use indexed operations correctly when selecting rows based on criteria involving multiple, indexed columnsMnesia:根据涉及多个索引列的条件选择行时如何正确使用索引操作
【发布时间】:2012-10-07 17:19:43
【问题描述】:

问题:

如何有效地从表中选择记录,其中选择基于涉及两个索引列的条件。

示例

我有记录,

#rec{key, value, type, last_update, other_stuff}
  • 我在 key(默认)、type 和 last_update 列上有索引
  • 类型通常是原子或字符串
  • last_update 是一个整数(自 1970 年以来的 unix 样式毫秒)

例如,我想要 type = Type 并且自特定时间戳以来已更新的所有记录。

我执行以下操作(包装在非脏事务中)

lookup_by_type(Type, Since) ->
    MatchHead = #rec{type=Type, last_update = '$1', _= '_'},
    Guard = {'>', '$1', Since},
    Result = '$_',
    case mnesia:select(rec,[{MatchHead, [Guard],[Result]}]) of
    []    -> {error, not_found};
    Rslts -> {ok, Rslts}
    end.

问题

  • lookup_by_type 函数是否使用底层索引?
  • 在这种情况下有没有更好的方法来利用索引
  • 我应该采取完全不同的方法吗?

谢谢大家

【问题讨论】:

    标签: erlang mnesia


    【解决方案1】:

    一种可能会对您有所帮助的方法是查看 QLC 查询。这些是更多的 SQL/声明性的,如果可能的话,他们将自己利用索引 IIRC。

    但主要问题是 mnesia 中的索引是散列,因此不支持范围查询。因此,您目前只能在type 字段上有效索引,而不能在last_update 字段上有效索引。

    解决此问题的一种方法是创建表ordered_set,然后将last_update 推为主键。如果您需要快速访问key 参数,则可以对其进行索引。一种存储可能性类似于:{{last_update, key}, key, type, ...}。因此您可以快速回答查询,因为last_update 是可订购的。

    另一种解决方法是单独存储上次更新。保留一个表{last_update, key},它是一个有序集,并使用它来限制在查询中对较大表进行扫描的数量。

    请记住,mnesia 最好用作小型内存数据库。因此,扫描不一定是问题,因为它们是在内存中的,因此速度非常快。但它的主要功能是能够以肮脏的方式对数据进行键/值查找以进行快速查询。

    【讨论】:

    • 如果我将主键 {last_update, key} 设置为 {0,SomeKey} 或 {12434,_} 的主键上的函数,与使用 ordered_set 和第二个键列相比效率更高按照你的建议?
    • 我进行了更改以使用 {LastUpdate,Key} 作为主键,并且在读取大量键时看到了一个数量级的改进。谢谢
    猜你喜欢
    • 1970-01-01
    • 2013-03-06
    • 2019-01-01
    • 2013-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-06
    • 1970-01-01
    相关资源
    最近更新 更多