2013-07-19 26 views
15

Potrzebuję przechowywać kilka miliardów małych struktur danych (około 200 bajtów każdy). Jak dotąd, przechowywanie każdego elementu jako oddzielnego dokumentu działa dobrze, a Mongo zapewnia około 10 000 wyników na sekundę. Używam 20-bajtowego skrótu jako _id dla każdego dokumentu i jednego indeksu w polu _id. W testowaniu działa to dla zestawów danych z 5 000 000 dokumentów.Strategie szybkiego wyszukiwania miliardów małych dokumentów w MongoDB

Podczas pracy wykonamy około 10 000 zgłoszeń na sekundę, aktualizując istniejące dokumenty około 1000 razy na sekundę i wstawiając nowe dokumenty może 100 razy na sekundę lub mniej.

W jaki sposób możemy zarządzać większymi zbiorami danych, gdy nie możemy przechowywać całego indeksu w pamięci RAM? Czy MongoDB będzie działał lepiej, jeśli połączymy kilka elementów w każdym dokumencie - w celu szybszego wyszukiwania w indeksie, ale więcej danych będzie zwracanych w każdym zapytaniu?

W przeciwieństwie do innych pytań na temat SO, interesuje mnie nie tylko to, ile danych możemy włożyć do Mongo. Może jasno zarządzać ilością danych, których szukamy. Obawiam się, w jaki sposób możemy zmaksymalizować prędkość operacji na dużych kolekcjach, z ograniczoną pamięcią RAM.

Nasze wyszukiwania będą klastry; około 50 000 elementów będzie spełniać około 50% zapytań, ale pozostałe 50% będzie losowo rozdzielane na wszystkie dane. Czy możemy oczekiwać wzrostu wydajności, przenosząc te 50% do swojej kolekcji, aby zachować mniejszy indeks najczęściej używanych danych zawsze w pamięci RAM?

Czy zmniejszenie rozmiaru pola _id z 20 bajtów do 8 bajtów ma znaczący wpływ na szybkość indeksowania MnogoDB?

+0

Wygląda na to, że będziesz miał znacznie więcej dokumentów niż pamięci RAM, dlatego zmniejszałbym dokumenty tak bardzo, jak to możliwe, aby zwiększyć ilość danych, które zmieszczą się w pamięci RAM. Upewnij się, że nazwy pól to tylko jeden lub dwa znaki na przykład. Planujesz odłamywać? Przeniesienie danych do odrębnej kolekcji na tym samym serwerze nie zmieni użycia pamięci RAM, ponieważ i tak jest zarządzany system operacyjny. – WiredPrairie

+0

Będziemy kłamać, gdy dane będą rosły. – Neil

+0

Umieszczenie najczęściej używanych rekordów w innej kolekcji jest tylko pomysłem, aby zachować indeks dla tej mniejszej kolekcji w pamięci RAM i nie dopuścić do jej zamiany. Myślę, że to może być naiwne, ale nie jestem pewien, dlaczego i dlaczego nie. – Neil

Odpowiedz

17

Kilka strategie przychodzą na myśl:

1) Użyj odrębną zbiórki/bazę danych dla dokumentów „gorących”.

Jeśli wiesz, które dokumenty są w gorącym zestawie, to pomoże Ci przeniesienie ich do oddzielnej kolekcji. Zapewni to, że gorące dokumenty będą współ-rezydentami na tym samym obszarze/stronach. Spowoduje to również, że indeks dla tych dokumentów będzie prawdopodobnie w pełni zapamiętywany. Wynika to z faktu, że jest on mniejszy i bycie (całkowicie?) Wykorzystywane częściej.

Jeśli gorące dokumenty są losowo mieszane z innymi dokumentami, najprawdopodobniej będziesz musiał uszkodzić więcej elementów liści indeksu B-Tree podczas ładowania dokumentu jako prawdopodobieństwo innego dokumentu, który ostatnio załadował lub uzyskał dostęp do indeksu blok jest mały.

2) Skróć indeksowane wartości .

Im krótsza wartość indeksu, tym więcej wartości mieści się w pojedynczym bloku B-Tree. (Uwaga: Klucze nie są uwzględnione w indeksie.) Im więcej wpisów w jednym segmencie oznacza mniejszą liczbę segmentów i mniejszą całkowitą ilość pamięci dla indeksu. Przekłada się to na wyższe prawdopodobieństwo/dłuższe okresy życia, które bloki pozostaną w pamięci. W twoim przykładzie redukcja 20-> 8 znaków jest lepsza niż 50% oszczędności. Jeśli możesz przekonwertować te 8 bajtów na długie, to jest trochę więcej oszczędności, ponieważ długie nie mają prefiksu długości (4 bajty) i końcowej wartości zerowej (łącznie 5 bajtów).

3) Skróć nazwy klawiszy.

Im krótsze pole, tym mniej miejsca zajmuje każdy dokument. Ma to niefortunny efekt uboczny zmniejszania czytelności.

4) Shard

To jest naprawdę jedynym sposobem na utrzymanie wyników Up w obliczu czyta poprzek całego corpus że wyczerpuje pamięć i ewentualne przepustowość dysku. Jeśli wykonasz odłamek, nadal będziesz chciał odrzucić "gorącą" kolekcję.

5) Adjust the read-ahead on disk to a small value.

Ponieważ „non-hot” czyta ładujesz dokument losową z dysku naprawdę chcą tylko do odczytu/usterki do pamięci tego dokumentu, jak i kilku dokumentów wokół niego, jak to możliwe. Większość systemów spróbuje odczytać duży blok danych, gdy użytkownik odczyta fragment pliku. Jest dokładnie odwrotnie, niż tego chcemy.

Jeśli zauważysz, że system bardzo źle działa, ale pamięć rezydentna dla procesu mongody nie zbliża się do dostępnej pamięci systemu, prawdopodobnie widzisz efekt bezużytecznych danych odczytu systemu operacyjnego.

6) Spróbuj użyć monotonicznie rosnących wartości dla kluczy.

Spowoduje to uruchomienie optymalizacji (dla indeksów opartych na ObjectId), która po podzieleniu bloku indeksu spowoduje to przy 90/10 zamiast 50/50. Powoduje to, że większość bloków w indeksie będzie w pobliżu pojemności, a będziesz potrzebował ich mniej.

Jeśli znasz tylko "gorące" 50 000 dokumentów po fakcie, to dodanie ich do oddzielnej kolekcji w kolejności indeksowej spowoduje również włączenie tej optymalizacji.

Rob.