2010-06-11 102 views
1

上午在烏干達喬希。我創建了一個mnesia分片表(64個片段),並設法將它填充到9948723條記錄。每個片段是一個disc_copies類型,有兩個副本。 現在,使用qlc(查詢列表理解)在搜索記錄時速度太慢,並且返回不準確的結果。使用QLC查詢mnesia碎片表返回錯誤結果

我發現這個開銷是qlc使用mnesia的select函數遍歷整個表以匹配記錄。我嘗試了下面的其他東西。

-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). 

雖然計算密集型,但工作得很好。 甚至在更改記錄定義後它仍然可以工作,因爲在編譯時它會得到新的記錄信息

問題是,當我在運行WinXP的3.0 GHz奔騰4處理器上啓動甚至25個進程時,很長時間才能返回結果。

如果我要在這些片段中使用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是一個數據結構,它定義了匹配表達式,返回值的塊大小e.t.c

當我試圖動態地構建匹配表達式時遇到了問題。

函數mnesia:讀/ 1或函數mnesia:讀/ 2,您需要有主鍵

現在問自己,我怎麼能有效地使用QLC在一個大的零散表搜索記錄?請幫忙。

我知道使用記錄的元組表示法會使代碼難以升級。這就是爲什麼 我討厭使用mnesia:select/1,mnesia:match_object/1,我想堅持QLC。 QLC在我的查詢中給出了錯誤的結果,即使在同一個節點上也有64個片斷的mnesia表。

有沒有人使用過QLC查詢分段表?請幫

回答

0

你調用在活動範圍內通活?

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.