Запрос фрагментированных таблиц mnesia с помощью QLC возвращает неверные результаты - PullRequest
2 голосов
/ 11 июня 2010

Джош в Уганде.я создал фрагментированную таблицу mnesia (64 фрагмента) и сумел заполнить ее до 9948723 записей.Каждый фрагмент имел тип disc_copies с двумя репликами.Теперь, используя qlc (понимание списка запросов), был слишком медлен в поиске записи и возвращал неточные результаты.

Я обнаружил, что это накладные расходы, что qlc использует функцию выбора mnesia, которая пересекает всютаблица для сопоставления записей.я попробовал что-то еще ниже.

-define(ACCESS_MOD,mnesia_frag).
-define(DEFAULT_CONTEXT,transaction).
-define(NULL,'_').
-record(address,{tel,zip_code,email}).
-record(person,{name,sex,age,address = #address{}}).

match()-> Z = fun(Spec) -> mnesia:match_object(Spec) end,Z.

match_object(Pattern)->
    Match = match(),
    mnesia:activity(?DEFAULT_CONTEXT,Match,[Pattern],?ACCESS_MOD).

Попытка этой функциональности дала мне хорошие результаты.Но я обнаружил, что мне нужно динамически создавать шаблоны для каждого поиска, который может быть выполнен в моих хранимых процедурах.

Я решил пройти через это, поэтому я написал функции, которые будут динамически создавать дикие шаблоны длямои записи в зависимости от того, какой параметр нужно искать.

%% This below gives me the default pattern for all searches ::= {person,'_','_','_'}

pattern(Record_name)->
    N = length(my_record_info(Record_name)) + 1,
    erlang:setelement(1,erlang:make_tuple(N,?NULL),Record_name).

%% this finds the position of the provided value and places it in that 
%% position while keeping '_' in the other positions.
%% The caller function can use this function recursively until
%% it has built the full search pattern of interest

pattern({Field,Value},Pattern_sofar)->
    N = position(Field,my_record_info(element(1,Pattern_sofar))),
    case N of
        -1 -> Pattern_sofar;
        Int when Int >= 1 -> erlang:setelement(N + 1,Pattern_sofar,Value);
        _ -> Pattern_sofar
    end.

my_record_info(Record_name)->
    case Record_name of
        staff_dynamic -> record_info(fields,staff_dynamic);
        person -> record_info(fields,person);
        _ -> []
    end.

%% These below,help locate the position of an element in a list
%% returned by "-record_info(fields,person)"

position(_,[]) -> -1;
position(Value,List)->
    find(lists:member(Value,List),Value,List,1).

find(false,_,_,_) -> -1;
find(true,V,[V|_],N)-> N;
find(true,V,[_|X],N)->
    find(V,X,N + 1).

find(V,[V|_],N)-> N;
find(V,[_|X],N) -> find(V,X,N + 1). 

Это работало очень хорошо, хотя и требовало больших вычислительных ресурсов.Он может работать даже после изменения определения записи, поскольку во время компиляции он получает новую информацию о записи

Проблема заключается в том, что когда я запускаю даже 25 процессов на процессоре Pentium 4 с тактовой частотой 3,0 ГГц, работающем под управлением WinXP, он зависает иВозвращение результатов занимает много времени.

Если я хочу использовать qlc в этих фрагментах, чтобы получить точные результаты, мне нужно указать, в каком фрагменте искать, как это.

find_person_by_tel(Tel)->
  select(qlc:q([ X || X <- mnesia:table(Frag), (X#person.address)#address.tel == Tel])).

select(Q)->
case ?transact(fun() -> qlc:e(Q) end) of
    {atomic,Val} -> Val;
    {aborted,_} = Error -> report_mnesia_event(Error) 
end.

Qlcвозвращал [], когда я что-то еще ищу, когда использую match_object / 1, я получаю точные результаты.Я обнаружил, что использование match_expressions может помочь.

mnesia: table (Tab, Props).где Props - это структура данных, которая определяет выражение соответствия, размер фрагмента возвращаемых значений и т. д.

У меня возникла проблема, когда я попытался построить выражения соответствия динамически.

Функция mnesia: read / 1 илиmnesia: read / 2 требует, чтобы у вас был первичный ключ

Теперь я спрашиваю себя, как я могу эффективно использовать QLC для поиска записей в большой фрагментированной таблице?Пожалуйста, помогите.

Я знаю, что использование кортежа представления записей затрудняет обновление кода.Вот почему я ненавижу использовать mnesia: select / 1, mnesia: match_object / 1, и я хочу придерживаться QLC.QLC дает мне неправильные результаты в моих запросах из таблицы мнезий из 64 фрагментов даже на одном узле.

Кто-нибудь когда-либо использовал QLC для запроса фрагментированной таблицы? Пожалуйста, помогите

1 Ответ

0 голосов
/ 20 августа 2012

Вы вызываете qlc в контексте активности?

tfn_match(Id) ->
    Search = #person{address=#address{tel=Id, _ = '_'}, _ = '_'},
    trans(fun() -> mnesia:match_object(Search) end).

tfn_qlc(Id) ->
    Q = qlc:q([ X || X <- mnesia:table(person), (X#person.address)#address.tel == Id]),
    trans(fun() -> qlc:e(Q) end).

trans(Fun) ->
    try Res = mnesia:activity(transaction, Fun, mnesia_frag),
    {atomic, Res}
    catch exit:Error ->
    {aborted, Error}
    end.
...