2011-11-04 9 views
13

Mamy kolekcję danych dziennika, gdzie każdy dokument w kolekcji jest identyfikowany przez adres MAC i dzień kalendarzowy. Zasadniczo:W MongoDB, strategia zwiększania wydajności zapisów do dzienników dzienników

{ 
    _id: <generated>, 
    mac: <string>, 
    day: <date>, 
    data: [ "value1", "value2" ] 
} 

Co pięć minut dołączamy nowy wpis dziennika do tablicy danych w dokumencie bieżącego dnia. Dokument przewija się o północy UTC, kiedy tworzymy nowy dokument dla każdego adresu MAC.

Zauważyliśmy, że IO, mierzone bajtami, zwiększa się przez cały dzień, a następnie spada z powrotem o północy UTC. Nie powinno się tak stać, ponieważ szybkość komunikatów dziennika jest stała. Uważamy, że nieoczekiwane zachowanie jest spowodowane przenoszeniem dokumentów Mongo, w przeciwieństwie do aktualizowania ich tablic rejestracyjnych w miejscu. O ile warto, stats() pokazuje, że paddingFactor ma wartość 1.0299999997858227.

Kilka pytań:

  1. Czy istnieje sposób, aby potwierdzić czy Mongo jest uaktualnienie na miejscu lub w ruchu? Widzimy pewne ruchy w dzienniku powolnego zapytania, ale wydaje się to niepotwierdzonym dowodem. Wiem, że mogę db.setProfilingLevel(2), a następnie db.system.profile.find(), a na koniec szukać "moved:true", ale nie jestem pewien, czy można to zrobić w zajętym systemie produkcyjnym.
  2. Rozmiar każdego dokumentu jest bardzo przewidywalny i regularny. Zakładając, że Mongo wykonuje wiele ruchów, jaki jest najlepszy sposób, aby się domyślić, dlaczego Mongo nie jest w stanie przewidzieć dokładniej? A może sprawić, by Mongo było bardziej precyzyjne? Zakładając, że powyższy opis problemu jest właściwy, poprawianie współczynnika dopełnienia nie wydaje się, aby to działało.
  3. To powinno być łatwe dla mnie, aby zatwierdzić dokument i usunąć domysły z Mongo. (Wiem, że doktorzy padding factor mówią, że nie powinienem tego robić, ale muszę po prostu zająć się tą kwestią.) Jaki jest najlepszy sposób na upominanie dokumentu? Wydaje się proste napisanie dokumentu z polem tablicy bajtów śmieci, a następnie natychmiastowe usunięcie tego pola z dokumentu, ale czy są jakieś błędy, o których powinienem wiedzieć? Na przykład, mogę sobie wyobrazić, że muszę czekać na serwerze na operację zapisu (to znaczy zrobić bezpieczny zapis) przed usunięciem pola śmieci.
  4. Byłem zaniepokojony wcześniejszym przydzieleniem wszystkich dokumentów dnia w tym samym czasie, ponieważ wydaje się, że to nasyciłoby dysk w tym czasie. Czy to jest ważny problem? Czy powinienem starać się rozłożyć koszty przedpłaty na poprzedni dzień?
+0

Scott Hernandez odpowiedział na to pytanie w grupie dyskusyjnej Google, a więc publikuję listę odpowiadającą jego odpowiedzi: http://groups.google.com/group/mongodb-user/browse_thread/thread/8a24e7f3faf95f71# – jtoberon

+0

Ostatnia aktualizacja: wciąż próbujemy zrozumieć, co się dzieje. – jtoberon

Odpowiedz

4

Poniższa kombinacja wydaje się powodować wydajność zapisu spaść z urwiska:

  1. dzienniku jest włączony.
  2. zapisy są dane do macierzy, który tworzy główną część większej dokumencie

Przypuszczalnie we/wy przestaje być nasycone.Zmiana jednego z tych czynników wydaje się uniemożliwiać takie działanie:

  1. Wyłącz dziennik. Zamiast tego użyj więcej replik.
  2. Użyj mniejszych dokumentów. Należy zauważyć, że rozmiar dokumentu jest tutaj mierzony w bajtach, a nie w długości jakichkolwiek tablic w dokumentach.
  3. Czasopismo w oddzielnym systemie plików.

Dodatkowo, oto kilka innych sztuczek poprawiających wydajność zapisu. Z wyjątkiem odłamków, stwierdziliśmy, że ulepszenia mają charakter przyrostowy, podczas gdy próbowaliśmy rozwiązać problem "to nie działa", ale uwzględniam je tutaj, na wypadek, gdy szukasz stopniowych ulepszeń . Użytkownicy 10Gen: did some testing and got similar results:

  1. Shard.
  2. Podział długich tablic na kilka tablic, aby ogólna struktura wyglądała jak drzewo zagnieżdżone. Jeśli jako klucz zostanie użyta godzina dnia, wówczas dziennik dziennika stanie się:
    {"0":[...], "1":[...],...,"23":[...]}.
  3. Spróbuj ręcznie dokonać wstępnej alokacji. (To nam nie pomogło, podszewka Mongo wydaje się działać jak w reklamie. Moje pierwotne pytanie było błędne.)
  4. Spróbuj różnych wartości --syncdelay. (To nam nie pomogło.)
  5. Spróbuj bez bezpiecznych zapisów. (Robiliśmy to już dla danych dziennika i nie jest to możliwe w wielu sytuacjach.) Wydaje się, że to trochę oszustwo.)

Zauważysz, że skopiowałem niektóre sugestie od 10Gen tutaj, tylko dla kompletności. Mam nadzieję, że zrobiłem to dokładnie! Jeśli opublikują przykład książki kucharskiej, opublikuję tutaj link.

0

mongodb będzie starał się dostosowywać dokumenty w sposób dostosowany, ponieważ dowiaduje się, w jaki sposób aktualizujesz dokumenty przez pewien okres czasu. Więcej informacji można znaleźć pod adresem http://www.mongodb.org/display/DOCS/Padding+Factor

Jeśli zauważysz, że mongodb nadal przesuwa dokumenty po pewnym czasie, możesz wypróbować ręczne dopełnienie dokumentu, abyś nie musiał się martwić o konieczność przenoszenia dokumentów.

W twoim przypadku wydaje się, że powinieneś być w stanie to zrobić, biorąc pod uwagę fakt, że liczba próbek w ciągu dnia jest stała (w twoim 5-minutowym przedziale). Czy możesz wydrukować dane wyjściowe z db. {Yourcollectionname} .stats()?

Odnośnie punktu # 4: Możesz rozłożyć koszty, jak wspomniałeś, ale chciałbym spróbować wstawić dokumenty, gdy są potrzebne po raz pierwszy, aby zobaczyć, jak to działa, a następnie wypróbować inne rzeczy.

Być może jesteś w stanie ominąć ten konkretny problem, badając inne schematy, ale nie jestem pewien, co wypróbowałeś.Czy przechowujesz kluczowe pary wartości w tablicy, a znacznik czasu jest kluczem? przykład modyfikacji będzie poruszać się do czegoś podobnego: { ID: 1, Dane: { "00:05": { "metric1": "wartosc1"}, "00:10": { " metric2 ":" value2 "} } }

+0

Jestem świadomy adaptacyjnej presalizacji, ale jeśli to działało, nie sądzę, żebyśmy zobaczyli wzór IO, który opisałem. Dodam statystyki do pytania. Tak, chciałbym ręcznie podeprzeć dokument; zobacz moje pytanie 3. Czy możesz podać szczegółowe informacje o tym, jak to zrobić? Tak, próbujemy rzeczy, ale jak już powiedziałem, oczekuję problemów, więc odpowiedź kogoś z doświadczeniem byłaby bardziej pomocna. Nie sądzę, że schemat jest rdzeniem tego problemu, ponieważ każde zapisanie dodaje wartość do końca pola tablicy, ale dodałem przykład do pytania na wszelki wypadek. – jtoberon

+0

jaki jest współczynnik wypełnienia, który mongotb obliczył dla swojej kolekcji? – Shekhar

+0

jest w pytaniu: 1.0299999997858227 – jtoberon

0

Wykonujesz przewidywalną/stałą liczbę naciśnięć w swojej tablicy danych. (24 * 60)/5 = 288 w jeden dzień. Zdecydowanie sugerowałbym wstępne przydzielenie 288 elementów tablicy (lub 1000 dla elastyczności i rozszerzenia w przypadku, gdy zdecydujesz się zrobić to co 3 minuty na przykład) w dokumencie, a następnie aktualizowanie dokumentu odpowiednio dla każdego dodania wpisu danych. Oto, jak postępować:

-Dodaj 1 dodatkowy klucz do każdego dokumentu, to zachowa numer klucza do aktualizacji w tablicy asocjacyjnej data. na przykład. Początkowo dokument będzie wyglądał na pierwszej wkładki lub odświeżeniu tablicy danych przez aktualizacji:

{ 
     _id: <generated>, 
     mac: <string>, 
     day: <date>, 
     data: { "1" : "myGarbageValue","2" : "myGarbageValue", 
       "3" : "myGarbageValue"....."1000": "myGarbageValue" } 
     n: 1 
} 

Dla każdej aktualizacji, trzeba zrobić upsert na data kluczowego równej n i przyrost n po 2 aktualizacje dane:

{ 
      _id: <generated>, 
      mac: <string>, 
      day: <date>, 
      data: { "1" : "myFirstValue","2" : "mySecondValue", 
        "3" : "myGarbageValue"....."1000": "myGarbageValue" } 
      n: 3 
    } 

Plusy:

  • Mniej wzrost dokumentu, to b Najlepiej jeśli twój myGarbageValue, myFirstValue,jest zgodny z rozmiarem i formatem.
  • n zawsze informuje o aktualnym rozmiarze macierzy data i umożliwia uruchamianie zapytań o zakres w celu znalezienia rozmiaru tablicy data, co nie było możliwe w poprzedniej strukturze, ponieważ operator $ size może zwracać tylko dokładne dopasowanie wielkości, a nie zakresy. http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24size
  • Zwiększenie wydajności jest lepsze, gdy dokument nie jest rozwijany. Tutaj jest oparty na czystym kluczu, np. Na data.23, podczas gdy w starej strukturze był to $push, który ma liniową wydajność wstawiania i zmniejsza się wraz ze wzrostem macierzy data.

Wady:

  • więcej miejsca na dysku jest wykorzystywane przez swoich danych, to nie powinno być problemem, jak odświeżyć swoje dane co 24 godziny.

Mam nadzieję, że te sugestie pomogą. Wypróbuj go i niech każdy z nas wie, czy ci to pomoże.

+0

Czy znasz oficjalne źródło informacji o funkcji "wypychania ma liniową wydajność wstawiania"? Znam ten test http://blog.axant.it/archives/236, ale twierdzi on tylko "prawdopodobnie". Spróbujemy zaproponować skojarzeniową tablicę, ale byłbym zaskoczony, gdyby to działało. Mamy już poniżej 5000 progu, o którym wspomniano. Ponadto, nie mogę wymyślić wyjaśnienia, dlaczego liniowy algorytm wstawiania przekładałby się na fizyczne zachowanie IO, które widzimy, ponieważ nie może poruszać każdego wpisu. – jtoberon

+0

Witaj, jtoberon, Nie oficjalnie udokumentowane, ale zostało to zaobserwowane podczas niektórych testów porównawczych. Jednak w przypadku tablicy o niewielkich rozmiarach 288, takich jak Twoje, nie będzie to miało większego znaczenia. I masz rację, różnica IO nie wynika z różnicy algorytmów wstawiania/aktualizacji, jest ona spowodowana faktem, że z powodu wstępnej alokacji elementów w tablicy asocjacyjnej, twój obiekt dokumentu nie rośnie. Stąd ruchy wykonywane przez mongody są mniejsze , mniej IO. – DhruvPathak

+0

Asocjacyjna zmiana tablicy nie pomogła. Ładunek we/wy wygładza się, ale na poziomie gorszym od szczytów tego, co widzimy, gdy używamy zwykłej tablicy i '$ push'. – jtoberon