为何Erlang记录的首个元素无法作为Mnesia表的索引?
为什么Erlang记录的首个元素无法作为Mnesia表的索引?
当你尝试将Erlang记录的第一个字段设为Mnesia表的索引时,会遇到表创建失败的问题,但把该字段调整到非首位置后就能成功,具体现象如下:
执行失败的代码示例
(hlu@192.168.0.40)16> rd(pilot, {id, name, weight, phone}). pilot (hlu@192.168.0.40)17> mnesia:create_table(pilot, (hlu@192.168.0.40)17> [{attributes, record_info(fields, pilot)}, (hlu@192.168.0.40)17> {index, [#pilot.id]}, (hlu@192.168.0.40)17> {disc_copies, Nodes}, (hlu@192.168.0.40)17> {type, set}]). {aborted,{bad_type,pilot,{index,[{2,ordered}]}}}
执行成功的代码示例
(hlu@192.168.0.40)18> rf(pilot). ok (hlu@192.168.0.40)19> rd(pilot, {name, weight, phone, id}). pilot (hlu@192.168.0.40)20> mnesia:create_table(pilot, (hlu@192.168.0.40)20> [{attributes, record_info(fields, pilot)}, (hlu@192.168.0.40)20> {index, [#pilot.id]}, (hlu@192.168.0.40)20> {disc_copies, Nodes}, (hlu@192.168.0.40)20> {type, set}]). {atomic,ok}
原因解释
Mnesia的set类型表有个默认规则:记录的第一个属性会自动成为表的主键,而主键本身已经自带了索引功能,Mnesia不允许给主键字段额外创建显式索引——这属于重复操作,会触发类型错误。
在失败的示例中,id是记录的第一个属性,创建set表时它自动成为主键,此时你试图把id加入index列表,就会抛出bad_type错误。错误信息里的{2,ordered}对应主键在元组中的位置(因为Erlang记录的第一个元素是记录名,所以属性id是元组的第2个元素)。
而成功的示例中,id被移到了记录的最后一位,此时表的主键变成了第一个属性name,id不再是主键,因此可以给它创建索引,表创建操作顺利完成。
补充说明
如果你本来就打算用id作为表的主键,那根本不需要额外给它加索引——主键本身就支持高效的查询,直接省略{index, [#pilot.id]}这个配置项即可正常创建表。
内容的提问来源于stack exchange,提问作者Gabor Szelei
相关产品推荐
相关产品推荐

