Zmniejszanie rozmiaru pliku bazy danych MongoDB

165

Mam bazę danych MongoDB, która kiedyś była duża (> 3 GB). Od tego czasu dokumenty zostały usunięte i spodziewałem się, że rozmiar plików bazy danych odpowiednio się zmniejszy.

Ale ponieważ MongoDB zachowuje przydzielone miejsce, pliki są nadal duże.

Czytałem tu i tam, że mongod --repairdo zwolnienia nieużywanego miejsca służy polecenie administratora , ale nie mam wystarczającej ilości miejsca na dysku, aby uruchomić to polecenie.

Czy znasz sposób, w jaki mogę zwolnić niewykorzystane miejsce?

Meuble
źródło
7
Czy to pytanie jest uważane za udzielone? Czy potrzebujemy więcej danych?
Wiceprezes Gates
2
począwszy od wersji 2.8 możesz skompresować swoje dane , co oszczędza znaczną ilość miejsca.
Salvador Dali,
1
Miałem dokładnie to samo wyzwanie, najłatwiej było go rozwiązać, wykonując kopię bazy danych za pomocą funkcji copyDatabase (), następnie do bazy danych db.dropDatabase () z oryginalnej bazy danych i kopiując ją z powrotem na miejsce. moja baza danych była w większości pusta, a kiedy wykonywałem kopię, kopiowane były tylko rzeczywiste dane użyteczne. upuszczenie oryginalnej bazy danych spowodowało usunięcie dużych plików. użycie metody db.repairDatabase () nie wchodziło w grę, ponieważ na moim serwerze było już mało miejsca na dysku, a ta operacja wymagałaby bardzo dużej ilości wolnego miejsca, znacznie większej niż jest to konieczne do tej operacji.
user3892260

Odpowiedzi:

144

UPDATE: za pomocą compactpolecenia i WiredTiger wygląda na to, że dodatkowe miejsce na dysku zostanie faktycznie zwolnione do systemu operacyjnego .


AKTUALIZACJA: od wersji 1.9 + jest compactpolecenie.

To polecenie wykona zagęszczanie „w linii”. Nadal będzie potrzebować dodatkowej przestrzeni, ale nie tak dużo.


MongoDB kompresuje pliki przez:

  • kopiowanie plików do nowej lokalizacji
  • przeglądanie dokumentów i ponowne porządkowanie / ponowne ich rozwiązywanie
  • zastąpienie oryginalnych plików nowymi plikami

Możesz to zrobić "kompresję" uruchamiając mongod --repairlub łącząc się bezpośrednio i uruchamiając db.repairDatabase().

W obu przypadkach potrzebujesz miejsca na skopiowanie plików. Teraz nie wiem, dlaczego nie masz wystarczająco dużo miejsca, aby wykonać kompres, jednak masz kilka opcji, jeśli masz inny komputer z większą ilością miejsca.

  1. Wyeksportuj bazę danych na inny komputer z zainstalowanym Mongo (używając mongoexport), a następnie możesz zaimportować tę samą bazę danych (używając mongoimport). Spowoduje to, że nowa baza danych będzie bardziej skompresowana. Teraz możesz zatrzymać oryginałmongod zastąpienie nowymi plikami bazy danych i gotowe.
  2. Zatrzymaj bieżący mongod i skopiuj pliki bazy danych na większy komputer i uruchom naprawę na tym komputerze. Następnie możesz przenieść nowe pliki bazy danych z powrotem na oryginalny komputer.

Obecnie nie ma dobrego sposobu na „kompaktowanie w miejscu” przy użyciu Mongo. A Mongo z pewnością może pochłonąć dużo miejsca.

Obecnie najlepszą strategią zagęszczania jest uruchomienie konfiguracji Master-Slave. Następnie możesz skompaktować Slave, pozwolić mu dogonić i przełączyć je. Wiem, że wciąż jestem trochę włochaty. Może zespół Mongo wymyśli lepsze zagęszczanie na miejscu, ale nie sądzę, aby to było wysoko na ich liście. Obecnie zakłada się, że przestrzeń dyskowa jest tania (i zwykle tak jest).

Gates VP
źródło
Dziękuję Gates VP za odpowiedź. Myślałem o dwóch opcjach, o których wspomniałeś. Ale zanim zrobiłem takie rzeczy, chciałem wiedzieć, czy dostępne jest kompaktowe rozwiązanie na miejscu. Dzięki jeszcze raz.
Meuble
3
Na dzień dzisiejszy (18.11.2010) Dwight (przemawiając na konferencji MongoDC w Waszyngtonie) zalecił podejście replicate / --repair / switch over, jeśli chcesz kompaktować bez przełączania bazy danych w tryb offline.
David J.
10
Wystarczy jedno ostrzeżenie „nie rób tak jak ja” i uruchom - napraw jako root. kieruje pliki db do katalogu głównego. doh.
Totoro
18
Dokumentacja „kompaktowa” mówi: „Ta operacja nie zmniejszy ilości miejsca na dysku używanego w systemie plików”. Nie rozumiem, jak to jest rozwiązanie pierwotnego pytania.
Ed Norris
Jeśli spojrzysz na pierwotne pytanie, część problemu polegała na posiadaniu zbyt dużej ilości danych do wykonania naprawy. Jeśli wypełniłeś 2/3 dysku jedną DB, nie możesz wykonać naprawy. Nowo przydzielone pliki zajęłyby pozostałe miejsce, zanim nowa baza danych została całkowicie „skopiowana i naprawiona”, a „zmiana” nigdy by się nie odbyła. Dzięki compacttemu może przynajmniej zachować istniejące pliki. Zgadzam się, to nie jest pełne rozwiązanie, ale jest to stopniowa poprawa.
Gates VP,
39

Miałem ten sam problem i rozwiązałem go po prostu robiąc to w wierszu poleceń:

mongodump -d databasename
echo 'db.dropDatabase()' | mongo databasename
mongorestore dump/databasename
user435943
źródło
assertion: 15936 Tworzenie kolekcji db.collection nie powiodło się. Errmsg: wyjątek: określ rozmiar: <n> gdy ograniczenie jest prawdziwe
poprawka 2
: Wygląda na regresję Ubuntu ... plik zrzutu ma ograniczenie metadanych: „niezdefiniowane” w nim ... usunięcie tych elementów rozwiązuje problem z importem.
poprawka 2
2
Moja baza danych oceniła prawie cały dysk. było to 120 GB (dysk 160 GB) Kompakt nie zmniejsza rozmiaru pliku i naprawa bazy danych nie jest możliwa z powodu braku miejsca. Po mongodump & dropDatabase i mongorestore db mam 40 GB pojemności bazy danych.
Igor Benikov
Mała poprawka do polecenia przywracaniamongorestore --db databasename dump/databasename
JERRY
34

Wygląda na to, że Mongo v1.9 + obsługuje wersję kompaktową!

> db.runCommand( { compact : 'mycollectionname' } )

Zobacz dokumentację tutaj: http://docs.mongodb.org/manual/reference/command/compact/

„W przeciwieństwie do repairDatabase, polecenie compact nie wymaga podwójnego miejsca na dysku do wykonania swojej pracy. Wymaga niewielkiej ilości dodatkowej przestrzeni podczas pracy. Dodatkowo, kompaktowanie jest szybsze”.

awaage
źródło
3
@AnujGupta "Polecenie repairDatabase kompaktuje wszystkie kolekcje w bazie danych. Działa to tak samo, jak uruchamianie polecenia compact dla każdej kolekcji indywidualnie." docs.mongodb.org/manual/reference/command/repairDatabase/… . Więc jeśli repairDatabase zmniejszy rozmiar tak, aby był kompaktowy. Kompaktowałem swoje kolekcje z dużą ilością usuwania i aktualizacji co tydzień. Bardziej podoba mi się kompaktowanie niż repariDatabase, ponieważ najpierw jest skierowane do kolekcji, których nie chcesz mieć całej bazy danych. Po drugie, potrzebuje tylko 2 GB wolnego miejsca zamiast x2 rozmiaru pliku db (w moim przypadku 500 GB).
Maziyar
1
Przy okazji sprawdź to: „MongoDB zapewnia 2 różne sposoby kompaktowania danych i przywracania optymalnej wydajności: naprawa bazy danych i kompaktowanie. Naprawa bazy danych jest odpowiednia, jeśli bazy danych są stosunkowo małe lub możesz pozwolić sobie na wyłączenie węzła z rotacji na długi czas . Ze względu na rozmiary naszych baz danych i obciążenie zapytaniami bardziej sensowne było ciągłe kompaktowanie wszystkich naszych kolekcji ”. blog.parse.com/2013/03/26/always-be-compacting github.com/ParsePlatform/Ops/blob/master/tools/mongo_compact.rb
Maziyar
3
@Maziyar docs.mongodb.org/manual/reference/command/compact/#disk-space - „W przeciwieństwie do repairDatabase, kompaktowanie nie zwalnia miejsca w systemie plików”.
Anuj Gupta,
4
@Maziyar OP chce zwolnić niewykorzystane miejsce , co jest osiągane przez repairDatabase, a nie compact. compactnie zwalnia miejsca, a jedynie defragmentuje zajęte miejsce, co go nie zmniejsza.
Anuj Gupta
5
Jak Mongo 3.0, compact będzie odzyskać miejsce w przypadku korzystania z mechanizmu przechowywania WiredTiger.
Gary,
19

Kompaktuj wszystkie kolekcje w bieżącej bazie danych

db.getCollectionNames().forEach(function (collectionName) {
    print('Compacting: ' + collectionName);
    db.runCommand({ compact: collectionName });
});
OzzyCzech
źródło
13

Jeśli chcesz przeprowadzić pełną naprawę, użyj repairpath opcji. Skieruj go na dysk z większą dostępną przestrzenią.

Na przykład na moim Macu użyłem:

mongod --config /usr/local/etc/mongod.conf --repair --repairpath /Volumes/X/mongo_repair

Aktualizacja: dla MongoDB Core Server Ticket 4266 może być konieczne dodanie, --nojournalaby uniknąć błędu:

mongod --config /usr/local/etc/mongod.conf --repair --repairpath /Volumes/X/mongo_repair --nojournal
David J.
źródło
1
To działało świetnie. Brakowało mi 2x miejsca wymaganego do naprawy na miejscu, więc zamontowałem NAS. Jedyny problem, ukończenie go zajęło 18 godzin, ale zadziałało. Pamiętaj, aby dodać flagę --nojoural.
zenocon
11

Począwszy od wersji 2.8 Mongo, możesz używać kompresji . Będziesz mieć 3 poziomy kompresji z silnikiem WiredTiger, mmap (który domyślnie w 2.6 nie zapewnia kompresji):

Oto przykład, ile miejsca będziesz mógł zaoszczędzić na 16 GB danych:

wprowadź opis obrazu tutaj

dane pochodzą z tego artykułu.

Salvador Dali
źródło
7

Musimy rozwiązać 2 sposoby, w oparciu o StorageEngine.

1. Silnik MMAP ():

polecenie: db.repairDatabase ()

UWAGA: repairDatabase wymaga wolnego miejsca na dysku równego rozmiarowi bieżącego zestawu danych plus 2 gigabajty. Jeśli wolumin zawierający dbpath nie ma wystarczającej ilości miejsca, możesz zamontować oddzielny wolumin i użyć go do naprawy. Podczas montowania oddzielnego woluminu do naprawy bazy danych repairDatabase należy uruchomić repairDatabase z wiersza poleceń i użyć przełącznika --repairpath, aby określić folder, w którym mają być przechowywane tymczasowe pliki napraw. np .: Wyobraź sobie, że rozmiar bazy danych wynosi 120 GB, (120 * 2) +2 = wymagane 242 GB miejsca na dysku twardym.

inny sposób na mądre zbieranie danych, polecenie: db.runCommand ({compact: 'nazwa_kolekcji'})

2. WiredTiger: automatycznie rozwiązuje się sam.

Karthickkumar Nagaraj
źródło
6

Nastąpiło spore zamieszanie w kwestii odzyskiwania przestrzeni w MongoDB, a niektóre zalecane praktyki są wręcz niebezpieczne w przypadku niektórych typów wdrożeń. Więcej szczegółów poniżej:

TL; DR repairDatabase próbuje odzyskać dane z autonomicznych wdrożeń MongoDB, które próbują odzyskać dane po uszkodzeniu dysku. Jeśli odzyska miejsce, jest to efekt uboczny . Odzyskiwanie miejsca nigdy nie powinno być głównym celem podczas biegania repairDatabase.

Odzyskaj miejsce w samodzielnym węźle

WiredTiger: W przypadku samodzielnego węzła z WiredTiger uruchomienie compactspowoduje zwolnienie miejsca w systemie operacyjnym z jednym zastrzeżeniem: compactna polecenie w WiredTiger w MongoDB 3.0.x wystąpił ten błąd: SERVER-21833, który został naprawiony w MongoDB 3.2.3. Przed tą wersjącompact na WiredTiger mógł po cichu zawieść.

MMAPv1: Ze względu na sposób działania MMAPv1 nie ma bezpiecznej i obsługiwanej metody odzyskiwania miejsca przy użyciu silnika pamięci MMAPv1. compactw MMAPv1 zdefragmentuje pliki danych, potencjalnie udostępniając więcej miejsca na nowe dokumenty, ale nie zwalnia miejsca z powrotem do systemu operacyjnego.

Państwo może być w stanie uruchomić repairDatabase, jeśli w pełni zrozumieć konsekwencje tego potencjalnie niebezpiecznego polecenia (patrz poniżej), ponieważrepairDatabase w istocie przepisuje całą bazę odrzucając uszkodzone dokumenty. Efektem ubocznym jest utworzenie nowych plików danych MMAPv1 bez jakiejkolwiek fragmentacji i zwolnienie miejsca z powrotem do systemu operacyjnego.

Aby uzyskać mniej ryzykowną metodę, uruchom mongodumpi mongorestoremoże być również możliwe we wdrożeniu MMAPv1, w zależności od rozmiaru wdrożenia.

Zwolnij miejsce w zestawie replik

W przypadku konfiguracji zestawu replik najlepszą i najbezpieczniejszą metodą odzyskania miejsca jest wykonanie początkowej synchronizacji , zarówno dla WiredTiger, jak i MMAPv1.

Jeśli chcesz odzyskać miejsce ze wszystkich węzłów w zestawie, możesz przeprowadzić kroczącą synchronizację początkową. Oznacza to, że wykonaj początkową synchronizację na każdym z elementów pomocniczych, zanim ostatecznie zejdziesz z podstawowego i wykonaj na nim początkową synchronizację. Metoda wstępnej synchronizacji kroczącej jest najbezpieczniejszą metodą wykonywania konserwacji zestawu replik, a dodatkowo nie wiąże się z żadnymi przestojami.

Należy pamiętać, że możliwość wykonania stopniowej wstępnej synchronizacji zależy również od rozmiaru wdrożenia. W przypadku bardzo dużych wdrożeń wykonanie początkowej synchronizacji może nie być możliwe, a zatem opcje są nieco bardziej ograniczone. Jeśli jest używany WiredTiger, to może być w stanie podjąć jedną wtórną Spośród zestawu, należy go uruchomić jako samodzielny, prowadzonym compactna nim, i dołączyć go do zestawu.

Jeżeli chodzi o repairDatabase

Nie uruchamiaj repairDatabasena węzłach zestawu replik . Jest to bardzo niebezpieczne, o czym wspomniano na stronie naprawy bazy danych i opisano bardziej szczegółowo poniżej.

Nazwa repairDatabasejest nieco myląca, ponieważ polecenie nie próbuje niczego naprawiać. Polecenie było przeznaczone do użycia w przypadku uszkodzenia dysku w samodzielnym węźle , co może prowadzić do uszkodzenia dokumentów.

repairDatabaseKomenda może być bardziej dokładnie opisane jako „bazy” salvage. Oznacza to, że odtwarza bazy danych, odrzucając uszkodzone dokumenty w celu wprowadzenia bazy danych do stanu, w którym można ją uruchomić i odzyskać z niej nienaruszony dokument.

We wdrożeniach MMAPv1 ta przebudowa plików bazy danych zwalnia miejsce w systemie operacyjnym jako efekt uboczny . Zwolnienie miejsca dla systemu operacyjnego nigdy nie było celem.

Konsekwencje repairDatabasena zestawie replik

W zestawie replik MongoDB oczekuje, że wszystkie węzły w zestawie będą zawierać identyczne dane. Jeśli uruchomisz repairDatabasena węźle z zestawem replik, istnieje szansa, że ​​węzeł zawiera niewykryte uszkodzenie i repairDatabasesumiennie usunie uszkodzone dokumenty za Ciebie.

Jak można się było spodziewać, ten węzeł zawiera inny zestaw danych niż reszta zestawu. Jeśli aktualizacja dotrze do tego pojedynczego dokumentu, cały zestaw może się zawiesić.

Co gorsza, jest całkowicie możliwe, że sytuacja ta może pozostać uśpiona przez długi czas, by zaatakować nagle bez wyraźnego powodu.

kevinadi
źródło
5

W przypadku, gdy duża porcja danych zostanie usunięta z kolekcji, a kolekcja nigdy nie wykorzysta usuniętego miejsca na nowe dokumenty, to miejsce musi zostać zwrócone do systemu operacyjnego, aby mogło być wykorzystane przez inne bazy danych lub kolekcje. Będziesz musiał uruchomić operację kompaktowania lub naprawy, aby zdefragmentować miejsce na dysku i odzyskać dostępne wolne miejsce.

Zachowanie się procesu zagęszczania zależy od silnika MongoDB w następujący sposób

db.runCommand({compact: collection-name })

MMAPv1

Operacja kompaktowania powoduje defragmentację plików danych i indeksów. Jednak nie zwalnia miejsca w systemie operacyjnym. Operacja jest nadal przydatna do defragmentacji i tworzenia bardziej ciągłej przestrzeni do ponownego wykorzystania przez MongoDB. Jednak nie jest to przydatne, gdy ilość wolnego miejsca na dysku jest bardzo mała.

Podczas operacji kompaktowania wymagane jest dodatkowe miejsce na dysku do 2 GB.

Blokada poziomu bazy danych jest utrzymywana podczas operacji zagęszczania.

WiredTiger

Silnik WiredTiger domyślnie zapewnia kompresję, która zajmuje mniej miejsca na dysku niż MMAPv1.

Kompaktowy proces zwalnia wolne miejsce do systemu operacyjnego. Do uruchomienia operacji kompaktowania wymagana jest minimalna ilość miejsca na dysku. WiredTiger blokuje również wszystkie operacje w bazie danych, ponieważ wymaga blokady na poziomie bazy danych.

W przypadku silnika MMAPv1 funkcja kompaktowa nie zwraca miejsca na system operacyjny. Aby zwolnić niewykorzystane miejsce, musisz uruchomić operację naprawy.

db.runCommand({repairDatabase: 1})
VISHAL KUMAWAT
źródło
3

Mongodb 3.0 i nowsze mają nowy silnik pamięci masowej - WiredTiger. W moim przypadku zmiana silnika zmniejszyła zużycie dysku ze 100 Gb do 25 Gb.

Hett
źródło
1

Pliki bazy danych nie mogą być zmniejszane. Podczas „naprawy” bazy danych serwer mongo może usunąć tylko część swoich plików. Jeśli usunięto dużą ilość danych, serwer mongo „zwolni” (usunie) podczas naprawy część swoich istniejących plików.

ivankoni
źródło
1

Ogólnie rzecz biorąc, lepiej jest kompaktować niż naprawiać. Ale jedną z zalet naprawy w stosunku do kompaktowania jest możliwość naprawy całego klastra. compact, musisz zalogować się do każdego fragmentu, co jest trochę denerwujące.

user2077221
źródło
1

Kiedy miałem ten sam problem, zatrzymałem serwer mongo i uruchomiłem go ponownie za pomocą polecenia

mongod --repair

Przed przystąpieniem do naprawy należy sprawdzić, czy na dysku twardym jest wystarczająco dużo wolnego miejsca (min - to rozmiar bazy danych)

Alexander Makarov
źródło
1

W trybie samodzielnym możesz użyć kompaktowania lub naprawy,

W przypadku podzielonego na fragmenty klastra lub zestawu replik, z mojego doświadczenia wynika, że ​​po uruchomieniu kompaktowania na podstawowym, a następnie kompaktowania pomocniczej, rozmiar podstawowej bazy danych jest zmniejszony, ale nie pomocniczy. Możesz ponownie zsynchronizować członka, aby zmniejszyć rozmiar dodatkowej bazy danych. i robiąc to może się okazać, że rozmiar pomocniczej bazy danych jest jeszcze bardziej zmniejszony niż podstawowa, myślę, że polecenie compact nie zajmuje naprawdę kompaktowania kolekcji. Tak więc skończyło się na przełączaniu podstawowego i pomocniczego zestawu replik i ponownej synchronizacji członka .

Mój wniosek jest taki, że najlepszym sposobem zmniejszenia rozmiaru zestawu fragmentów / replik jest wykonanie ponownej synchronizacji elementu członkowskiego, przełączenie podstawowego pomocniczego i ponownej synchronizacji.

mądrość
źródło
0

MongoDB -repair nie jest zalecana w przypadku podzielonego na fragmenty klastra.

Jeśli używasz zestawu replik z fragmentami klastra, użyj polecenia kompaktowego, spowoduje to ponowne zapisanie i defragmentację wszystkich plików danych i indeksów wszystkich kolekcji. składnia:

db.runCommand( { compact : "collection_name" } )

przy użyciu siły: prawdziwe, kompaktowe działa na podstawowym zestawie replik. na przykład db.runCommand ( { command : "collection_name", force : true } )

Inne kwestie do rozważenia: -To blokuje operacje. więc zalecane do wykonania w oknie obsługi. -Jeśli zestawy replik działające na różnych serwerach muszą być wykonywane na każdym elemencie członkowskim osobno - W przypadku podzielonego na fragmenty klastra, kompaktowe musi być wykonywane na każdym elemencie fragmentu oddzielnie. Nie można wykonać przeciwko instancji mongosów.

Sok roślinny
źródło
-5

Tylko jeden sposób, w jaki mogłem to zrobić. Brak gwarancji bezpieczeństwa istniejących danych. Spróbuj na własne ryzyko.

Usuń pliki danych bezpośrednio i uruchom ponownie mongod.

Na przykład w przypadku ubuntu (domyślna ścieżka do danych: / var / lib / mongodb) miałem kilka plików o nazwach takich jak: collection. #. Zachowuję kolekcję. 0 i usunąłem wszystkie inne.

Wydaje się łatwiejsze, jeśli nie masz poważnych danych w bazie danych.

frnkxiao
źródło
pliki są przechowywane jako <nazwa_bazy_danych>. <numer> np. mydb.3 - nie możesz określić kolekcji.
bobmarksie