2015-04-12 44 views
2

例如,定記錄分頁搜索二郎Mnesia的

-record(item, { 
    id, 
    time, 
    status}). 

我想搜索的1000年至1100年的項目,按時間排序,並status =:= <<"finished">>

有什麼建議?

回答

2

這要看你的查詢是什麼樣子。如果你需要通過很多不同的列進行排序,那麼我會考慮使用SQL而不是Mnesia。

但是,如果您只需要您描述的那種查詢,您應該可以使用ordered_set類型的表來處理排序,並且mnesia:select/4可以處理分頁和約束。

下面是一些未經測試的代碼給你要點:

% time goes first because it's our primary sort key 
-record(statuses, {time, id, status}). 
... 
create_table() -> 
    mnesia:create_table(statuses, [ 
         {attributes, record_info(fields, statuses)} 
         ,{type, ordered_set} 
         ]). 

-spec fetch_paged(integer()) -> {[tuple()], continuation()}|'$end_of_table'. 
fetch_paged(PageSize) -> 
    MatchSpec = {#statuses{id = '$1', status = <<"finished">>, _ = '_'}, [], ['$1']}, 
    mnesia:select(statuses, [MatchSpec], PageSize, read). 

-spec next_page(continuation()) -> {[tuple()], continuation()}|'$end_of_table'. 
next_page(Cont) -> 
    mnesia:select(Cont). 

基本上,mnesia:select/4給你結果的頁面和結果的下一個頁面的延續。沒有一種內置的方法可以像SQL數據庫那樣跳到第1000條結果,所以如果你需要這種功能,你可以自己構建它(保留一個時間索引,以便快速查找表中的第1000個時間)是{{2015,4,12},{23,53,8}},然後運行select時使用,作爲一個後衛

+0

非常有幫助。不能有效地直接跳到第1000個結果的圖像 –

+0

我對Mnesia的(相對缺乏經驗)印象是,您可以將其視爲NoSQL DB(完全有意義的是您不能請求第1000頁)或您可以將其視爲關係數據庫,但沒有您從SQL數據庫(例如Postgres)獲得的頂層接口。所以如果你想要Mnesia *和*這些圖層,你需要自己構建它們。 (這基本上是BlackMamba使用fetch/sort/slice操作進行的操作,想象一下將它寫入一個gen_server,它會做一些緩存操作。) –

0

我想,你應該使用mnesia:select/2選擇哪個status =:= <<"finished">>,那麼你可以使用lists:sort通過time對結果進行排序,最後你可以使用lists:sublist/3的元素減去10001100的對象。

這裏是鏈接: http://www.erlang.org/doc/man/mnesia.html#select-2 http://www.erlang.org/doc/man/lists.html#sort-2 http://www.erlang.org/doc/man/lists.html#sublist-3

+0

你可以使用dirty_match_object和select/2來獲得不錯的加速。因爲你可能不關心分頁用例的一致性。如果你的數據集特別大,你將用完RAM來做到這一點。你需要使用像dirty_/next/2之類的東西。 –

0

你可能使用QLC光標,這樣的事情:

order(table_name,[id,Direction]) -> 
case Direction of 
    descent -> fun(A,B) -> A#table_name.id > B#table_name.id end; 
    ascent -> fun(A,B) -> A#table_name.id < B#table_name.id end 
end; 

select(universal,[Data_module,Table,Minor,Major,Order_by,Direction,Query]) -> 
try 
    if 
     Minor == Major -> {error}; 
     Minor == 0; Major == 0 -> {error}; 
     true -> 
      case apply(Data_module,order,[Table,[Order_by,Direction]]) of 
       error -> {error}; 
       Order -> 
        Transaction = fun() -> 
         Query = qlc:q([X||X <- mnesia:table(Table)]), 
         Handler = qlc:sort(Query,[{order,Order}]), 
         Cursor = qlc:cursor(Handler), 
         if 
          Minor == 1 -> 
           Result = qlc:next_answers(Cursor,Major), 
           qlc:delete_cursor(Cursor), 
           Result; 
          true -> 
           qlc:next_answers(Cursor,Minor-1), 
           Result = qlc:next_answers(Cursor,Major-Minor+1), 
           qlc:delete_cursor(Cursor), 
           Result 
         end 
        end, 
        mnesia:transaction(Transaction) 
      end 
    end 
catch 
    Exception:Reason -> {error} 
end. 

QLC的手冊是在這裏Qlc:reference 但這種方式並不是最快在中等負載的情況下是足夠的(每秒鐘測試10000個連接),但是在內存可用空間內你會遇到更多的問題,你需要將它升高到