假设您在节点A和B上复制了一个mnesia表.如果在节点C上,不包含表的副本,我会这样做mnesia:change_config(extra_db_nodes, [NodeA, NodeB]),然后在节点CI上做mnesia:dirty_read(user, bob)节点C如何选择哪个节点的表副本为执行查询?
我们的Mnesia DB运行缓慢,我们认为它应该更快一些.
因此,我们需要对其进行分析并找出正在发生的事情.
有许多选项表明自己:
然而,这些都是相当标准的性能监控样式工具.问题是我如何实际进行查询分析 - 哪些查询花费的时间最长.如果我们是Oracle或MySQL商店,我们只会运行一个查询分析器,它将返回需要很长时间才能运行的各种查询.这不是Mnesia似乎可用的工具.
所以问题是:
fprof作为性能分析工具的一个问题是它只会告诉您正在查看的特定查询.所以fprof告诉我X很慢,我调整它以加快速度.然后,低,看,操作Y(这是足够快)现在是狗慢.因此,我描述了Y,并意识到快速制作Y的方法是让X变慢.所以我最终做了一系列双边权衡......
我真正需要的是一种管理多边权衡的方法.我现在记录了2个实际用户活动的度量标准,我可以重放.这些日志代表了我想要优化的内容.
SQL数据库上的"正确"查询分析器将能够分析SQL语句的结构,例如具有以下形式的所有语句:
SELECT [fieldset] FROM [table] WHERE {field = *parameter*}, {field = *parameter*}
Run Code Online (Sandbox Code Playgroud)
并且说这个形式的285个查询平均需要0.37ms才能运行
他们说出了神奇的答案:这个表格的17个查询需要运行6.34秒并在表X上进行全表扫描,你应该在字段Y上放一个索引
当我在一组有代表性的用户活动中得到这样的结果集时,我可以开始在这一轮中进行权衡 - 并设计一个测试模式.
测试模式类似于:
我一直在使用Erlang足以"知道"没有像这样的查询分析器,我想知道的是其他人(必须有这个问题)对于mnesia优化的"理由".
在我理解Mnesia的过程中,我仍然在用关系术语思考.因此,我将把我的斗争放在这里,并寻求解决它们的最佳方法.
一对多关系 说我有一群人,
-record(contact, {name, phone}).
Run Code Online (Sandbox Code Playgroud)
现在,我知道我可以将手机定义为总是保存为列表,因此人们可以拥有多个电话号码,我想这是做到这一点的方式(是吗?我怎么会这样看,反过来,比如,找一个数字的名字?).
多对多关系 现在让我们假设我有多个团体可以让人们进去.团体名称没有任何意义,它们只是名字; 这个概念是"unix系统组"或"标签".天真的,我会把这个会员资格建模为一个支持者,比如
{groups [{friends, bool()}, {family, bool()}, {work, bool()}]} %% and so on...
Run Code Online (Sandbox Code Playgroud)
例如,作为上面"联系"记录中的字段.如果我希望能够快速查找基于组名的组中的所有成员,并且还希望能够查找个人注册的所有组,那么在mnesia中对此进行建模的最佳方法是什么?当然,我也可以将其建模为仅包含组标识符的列表.与mnesia一起使用时,对此进行建模的最佳方法是什么?
如果这个问题愚蠢,我道歉.关于mnesia的文档很多,但它缺乏(IMO)一些很好的整体使用示例.
我最近一直潜入Erlang,我决定使用Mnesia来完成我的数据库工作,因为它可以存储任何类型的Erlang数据结构而没有问题,可以轻松扩展,与列表推导一起使用等.
来自标准SQL数据库,大多数行可以并且应该由主键标识,通常是自动递增整数.默认情况下,Mnesia将行的第一个字段视为其键.据我所知,它也没有办法让自动递增的整数键.
鉴于我有这些虚构的记录代表我的表:
-record(user, {name, salt, pass_hash, email}).
-record(entry, {title, body, slug}).
-record(user_entry, {user_name, entry_title}).
Run Code Online (Sandbox Code Playgroud)
我认为使用用户名可能已经足够用于某些目的,就像条目标题一样,为了识别资源,但我该如何保持完整性?
假设用户更改了其名称,或者在编辑后更改了条目的标题.如何确保我的数据仍然正确相关?无论如何使用用户名更改每个表,听起来都是一个糟糕的主意.
在Mnesia实施某种主键系统的最佳方法是什么?
另外,如果第一个字段通常是密钥,那么像'user_entry'这样的中间表会如何呢?否则,在Mnesia中代表多对多关系会有什么更好的方式?
我有一组erlang节点通过Mnesia的"extra_db_nodes"复制他们的数据......我需要升级硬件和软件,所以当我从节点到节点时,我必须分离一些节点.
如何删除节点并仍然保留插入的数据?
[update]删除节点与添加节点一样重要.随着集群的增长,它也必须收缩.如果没有,那么Mnesia将忙于尝试向不存在的节点发送数据以填充队列并保持网络繁忙.
[ 最后更新 ]在通过erlang/mnesia源代码填写后,我能够确定不可能完全取消关联节点.虽然del_table_copy删除了表之间的链接,但它不完整.我会关闭这个问题,但没有一个密切的描述是足够的.
我正在使用erlang,mnesia和webmachine构建一个网站.我读过的大多数文档都赞扬了具有引用透明功能的优点.
问题是,所有数据库访问都是外部状态.这意味着任何命中数据库的方法都不再是引用透明的.
假设我在数据库中有一个用户对象和一些处理身份验证的函数.
参考不透明的函数可能看起来像:
handle_web_request(http_info) ->
is_authorized_user(http_info.userid),
...
%referentially opaque
is_authorized_user(userid) ->
User = get_user_from_db(userid),
User.is_authorized.
%referentially opaque
lots_of_other_functions(that_are_similar) ->
db_access(),
foo.
Run Code Online (Sandbox Code Playgroud)
引用透明度要求我最小化引用不透明代码的数量,因此调用者必须从数据库中获取对象并将其作为参数传递给函数:
handle_web_request(http_info) ->
User = get_user(http_info.userid),
is_authorized_user(User),
...
%referentially opaque
get_user(userid) ->
get_user_from_db(userid).
%referentially transparent
is_authorized(userobj) ->
userobj.is_authorized.
%referentially transparent
lots_of_other_functions(that_are_similar) ->
foo.
Run Code Online (Sandbox Code Playgroud)
上面的代码显然不是生产代码 - 它纯粹是出于说明目的而编写的.
我不想陷入教条.引用透明代码(如可证明的单元测试)的好处是否证明了不太友好的接口?我应该在追求传教的过程中走多远?
我试过这段代码:
print_next(Current) ->
case mnesia:dirty_next(muppet, Current) of
'$end_of_table' ->
io:format("~n", []),
ok;
Next ->
[Muppet] = mnesia:dirty_read({muppet, Next}),
io:format("~p~n", [Muppet]),
print_next(Next),
ok
end.
print() ->
case mnesia:dirty_first(muppet) of
'$end_of_table' ->
ok;
First ->
[Muppet] = mnesia:dirty_read({muppet, First}),
io:format("~p~n", [Muppet]),
print_next(First),
ok
end.
Run Code Online (Sandbox Code Playgroud)
但它太长了.我也可以使用dirty_all_keys然后遍历键列表,但我想知道是否有更好的方法来打印Mnesia表内容.
我有一个在Erlang中制作的服务器应用程序.在其中我有一个mnesia表,存储一些照片信息.本着"一切都是过程"的精神,我决定将该表包装在一个gen_server模块中,以便gen_server模块是唯一直接访问该表的
模块.查询和向该表添加信息是通过向该进程发送消息(具有注册名称)来完成的.我们的想法是会有几个客户端进程从该表中查询信息.
这很好用,但该gen_server模块没有状态.它需要的一切都存储在mnesia表中.那么,我想知道是否gen_server可能不是封装该表的最佳模型?
我应该简单地不将它作为一个过程,而只是通过该模块中的函数封装表吗?如果该模块中存在错误,这将导致调用进程崩溃,我认为这可能会更好,因为它只会影响单个客户端,而不是现在,当它会导致gen_server进程崩溃时,会导致
每个人无法访问该表(直到主管重新启动它).
任何输入都非常感谢.
我正在使用复制的mnesia数据库运行两个erlang节点.每当我尝试启动其中一个而mnesia不在另一个上运行时,mnesia:wait_for_tables(?TABS,?TIMEOUT)将挂在它调用的节点上.我需要有一个结构(如果两个节点都没有运行),我可以开始使用一个而另一个停止运行,然后决定将另一个运行起来但继续运行良好.我需要确保正在运行的第一个节点在启动时更新了后一个节点.这是否一定要我让一个作为主人?
%%%已编辑.............................................. .............................
哦,我知道了.我使用的数据库有几个碎片表.一些片段已经分布在整个网络中以实现负载平衡.因此,一个主机上的Mnesia会尝试在网络上加载它们并因为另一个主机上的mnesia停机而失败!
我想这与mnesia主节点无关.但是我仍然很想理解它的重要性,因为我之前没有使用它,但是,我总是使用分布式模式.
再次感谢...
我有一个mnesia表,其字段为f1,f2,f3.现在,如果我选择字段值为V1的所有行,我会使用mnesia:select和匹配规范或简单mnesia:match_object.现在我需要选择具有V1,V2,V3 ...或Vn(任意长度的列表)的所有行作为字段f1的值.在SQL中我会做类似的事情
SELECT * FROM tablename WHERE f3 IN (V1, V2, V3, ... , Vn)
Run Code Online (Sandbox Code Playgroud)
我怎么在mnesia这样做?