8

Piszę mały system na Javie, w którym wyodrębniam n-gramową funkcję z plików tekstowych, a później muszę przeprowadzić proces wyboru cech, aby wybrać najbardziej dyskryminujące funkcje.Najlepsza praktyka do przechowywania ogromnych list danych w Javie

Proces wyodrębniania funkcji dla pojedynczego pliku zwraca mapę, która zawiera każdą unikalną funkcję, jej wystąpienia w pliku. Łączę wszystkie mapy plików (mapę) w jedną mapę zawierającą częstotliwość dokumentów (DF) wszystkich unikalnych funkcji wyodrębnionych ze wszystkich plików. Ujednolicona mapa może zawierać ponad 10 000 000 wpisów.

Obecnie proces wyodrębniania funkcji działa doskonale i chcę przeprowadzić selekcję elementów, w której potrzebuję zastosować wzmocnienie informacji lub współczynnik wzmocnienia. Najpierw muszę posortować mapę, wykonać obliczenia i zapisać wyniki, aby w końcu uzyskać listę (dla każdej cechy, jej Wynik wyboru funkcji).

Moje pytanie brzmi: Co to jest najlepsza praktyka i najlepsze struktura danych do przechowywania dużej ilości danych (~ 10M) i wykonywania obliczeń?

+0

Spójrz na HashMap. – Hungry

Odpowiedz

1

Mam intuicję, że można czerpać inspirację z pierwotnego paradygmatu MapReduce i podzielić problem na kilka mniejszych, ale podobnych, a następnie zebrać te częściowe wyniki, aby osiągnąć kompletne rozwiązanie.

Jeśli rozwiążesz jedną, mniejszą instancję problemu naraz (to znaczy porcję pliku), to zagwarantuje ona zmniejszenie zużycia przestrzeni ograniczonej wymaganiami dotyczącymi miejsca dla tego pojedynczego wystąpienia.

Takie podejście do przetwarzania pliku leniwie będzie działać niezmiennie w wybranej strukturze danych.

1

Możesz użyć systemu buforowania, sprawdź MapDB jest bardzo wydajny i ma implementację mapy drzewa (dzięki czemu można uporządkować dane bez wysiłku). Udostępnia także magazyny danych, aby zapisać dane na dysku, gdy nie można ich przechowywać w pamięci.

// here a sample that uses the off-heap memory to back the map 
Map<String, String> map = DBMaker.newMemoryDirectDB().make().getTreeMap("words"); 

//put some stuff into map 
map.put("aa", "bb"); 
map.put("cc", "dd"); 
5

Jest to bardzo szerokie pytanie, więc odpowiedź również będzie szeroka. Rozwiązanie zależy (co najmniej) te trzy rzeczy:

  1. Wielkość swoimi wpisami

Przechowywanie 10.000.000 całkowite będzie wymagać o 40MiB pamięci, podczas przechowywania 10.000.000 x 1KiB rekordów będzie wymagać więcej niż 9GiB . To są dwa różne problemy. Dziesięć milionów liczb całkowitych jest trywialnych do zapisania w pamięci w dowolnej kolekcji Java, a zachowanie 9GiB w pamięci zmusi cię do dostrojenia i dostrojenia Jutowej Sterty i garbage collectora. Jeśli wpisy są jeszcze większe, powiedzmy 1 MB, możesz całkowicie zapomnieć o przechowywaniu w pamięci. Zamiast tego musisz skupić się na znalezieniu dobrej struktury danych zabezpieczonej dyskiem, może bazy danych.

  1. Sprzęt używasz

Przechowywanie dziesięć milionów płyt 1KiB na maszynie z 8 GiB pamięci RAM nie jest taka sama jak przechowywanie ich na serwerze z 128GiB . Rzeczy, które są prawie niemożliwe z poprzednią maszyną, są banalne z tym ostatnim.

  1. Rodzaj obliczeń (y) chcesz zrobić

Wspominałeś sortowania, więc takie rzeczy jak TreeMap lub może PriorityQueue przyjść do głowy. Ale czy to najbardziej intensywne obliczenia? A jaki jest klucz, którego używasz do ich sortowania? Czy planujesz lokalizować (zdobywać) jednostki na podstawie innych właściwości, które nie są kluczowe? Jeśli tak, to wymaga oddzielnego planowania. W przeciwnym razie musisz powtórzyć wszystkie 10 milionów wpisów.

Czy obliczenia są wykonywane w jednym wątku lub wielu wątkach? Jeśli możesz mieć równoczesne modyfikacje danych, to wymaga oddzielnego rozwiązania. Struktury danych, takie jak TreeMap i PriorityQueue, musiałyby być zablokowane lub zastąpione przez współbieżne struktury, takie jak ConcurrentLinkedHashMap lub ConcurrentSkipListMap.