Indeksowanie Mongoose w kodzie produkcyjnym

124

Zgodnie z dokumentacją Mongoose dla MongooseJSi MongoDB/ Node.js:

Po uruchomieniu aplikacji Mongoose automatycznie wywołuje ensureIndexkażdy indeks zdefiniowany w schemacie. Chociaż jest to przyjemne dla programowania, zaleca się wyłączenie tego zachowania w środowisku produkcyjnym, ponieważ tworzenie indeksu może mieć znaczący wpływ na wydajność. Wyłącz to zachowanie, ustawiając autoIndexopcję schematu na wartość false.

Wydaje się, że instruuje to usunięcie automatycznego indeksowania z Mongoose przed wdrożeniem, aby zoptymalizować Mongoose od instruowania Mongo, aby przeszedł i przeszedł przez wszystkie indeksy podczas uruchamiania aplikacji, co wydaje się mieć sens.

Jaki jest właściwy sposób obsługi indeksowania w kodzie produkcyjnym? Może zewnętrzny skrypt powinien generować indeksy? A może ensureIndexjest niepotrzebne, jeśli pojedyncza aplikacja jest jedynym czytnikiem / piszącym w kolekcji, ponieważ będzie kontynuować indeksowanie za każdym razem, gdy nastąpi zapis bazy danych?

Edycja: aby uzupełnić, MongoDB zapewnia dobrą dokumentację dotyczącą sposobu indeksowania, ale nie wyjaśnia, dlaczego lub kiedy należy wykonać jawne dyrektywy indeksowania. Wydaje mi się, że indeksy powinny być aktualizowane automatycznie przez aplikacje pisarza w kolekcjach z istniejącymi indeksami, a to ensureIndexjest raczej jednorazowa czynność (wykonywana, gdy stosowany jest nowy indeks), w którym to przypadku indeks Mongoose autoIndexpowinien być no-op przy normalnym restarcie serwera.

Nick S.
źródło

Odpowiedzi:

135

Nigdy nie rozumiałem, dlaczego dokumentacja Mongoose tak szeroko zaleca wyłączenie autoIndexw środowisku produkcyjnym. Po dodaniu indeksu kolejne ensureIndexwywołania po prostu zobaczą, że indeks już istnieje, a następnie powrócą. Więc ma to wpływ tylko na wydajność podczas tworzenia indeksu po raz pierwszy, a wtedy zbiory są często puste, więc utworzenie indeksu i tak byłoby szybkie.

Proponuję pozostawić autoIndexwłączone, chyba że masz konkretną sytuację, w której sprawia ci to kłopoty; na przykład jeśli chcesz dodać nowy indeks do istniejącej kolekcji zawierającej miliony dokumentów i chcesz mieć większą kontrolę nad tym, kiedy jest tworzony.

JohnnyHK
źródło
10
Mam pytanie do dodania ... A jeśli ustawię to jako fałszywe? Następnie indeksy zostaną utworzone, gdy wstawię dane, czy też muszę je jawnie utworzyć. Przykro mi, jeśli jest to pytanie dla początkujących, ale byłoby bardzo pomocne, gdybyś odpowiedział.
Saransh Mohapatra
5
@SaranshMohapatra Gdy autoIndexma wartość false, musisz wywołać w modelu sureIndexes, aby utworzyć jego indeksy.
JohnnyHK
Czy będę musiał nazywać to za każdym razem, czy tylko raz definiując model?
Saransh Mohapatra
@SaranshMohapatra podczas definiowania (kompilowania) modelu. Robię to przy pierwszym uruchomieniu aplikacji. Teraz najtrudniej jest zdecydować o usunięciu wszystkich indeksów i odtworzeniu ich na wypadek zmiany schematu.
Moss
3
@JohnnyHK, czy nadal zgadzasz się ze swoją odpowiedzią teraz, gdy mamy prawie 2016 rok?
Alexander Mills,
41

Chociaż zgadzam się z zaakceptowaną odpowiedzią, warto zauważyć, że zgodnie z instrukcją MongoDB nie jest to zalecany sposób dodawania indeksów na serwerze produkcyjnym:

Jeśli aplikacja zawiera operacje zapewniająIndex (), a indeks nie istnieje w przypadku innych problemów operacyjnych, utworzenie indeksu może mieć poważny wpływ na wydajność bazy danych.

Aby uniknąć problemów z wydajnością, upewnij się, że aplikacja sprawdza indeksy podczas uruchamiania za pomocą metody getIndexes () lub równoważnej metody dla sterownika i kończy pracę, jeśli nie istnieją odpowiednie indeksy. Zawsze buduj indeksy w instancjach produkcyjnych przy użyciu oddzielnego kodu aplikacji w wyznaczonych oknach obsługi.

Oczywiście tak naprawdę zależy to od struktury i wdrożenia aplikacji. Jeśli na przykład wdrażasz aplikację do Heroku i nie używasz funkcji wstępnego rozruchu Heroku , prawdopodobnie Twoja aplikacja w ogóle nie obsługuje żądań podczas uruchamiania, więc prawdopodobnie w tym czasie bezpiecznie jest utworzyć indeks.

Oprócz tego z zaakceptowanej odpowiedzi:

Więc ma to wpływ tylko na wydajność podczas tworzenia indeksu po raz pierwszy, a wtedy zbiory są często puste, więc utworzenie indeksu i tak byłoby szybkie.

Jeśli udało Ci się uzyskać model danych i zapytania na pierwszy raz, to jest w porządku i często tak jest. Jeśli jednak dodajesz nową funkcjonalność do swojej aplikacji, z nowym zapytaniem DB dotyczącym właściwości bez indeksu, często zdarza się, że dodajesz indeks do kolekcji zawierającej wiele istniejących dokumentów.

Jest to czas, w którym należy uważać przy dodawaniu indeksów i dokładnie rozważyć wpływ tego na wydajność. Na przykład możesz utworzyć indeks w tle :

db.ensureIndex({ name: 1 }, { background: true });
Tom Spencer
źródło
3
Ok, więc wszystko, co musisz zrobić, to NIE uruchamiać serwera, dopóki wszystkie wywołania zwrotne sureIndex nie zostaną uruchomione dla każdej kolekcji.
Alexander Mills,
@AlexMills, jak możesz to zapewnić?
lonelymo
async.each (Object.keys (modele), function (key, cb) {models [key] .ensureIndexes (cb)}, cb)
Alexander Mills,
po prostu wywołaj sureIndexes na każdym modelu mangusty, poczekaj, aż wszystko się skończy, a następnie uruchom serwer; Polecam również poczekać na nawiązanie połączeń db przed uruchomieniem serwera
Alexander Mills,
2
Już nie ensureIndexma. createIndexZamiast tego jest . Czy mam rację?
puste gniazdo jack
1

użyj tego kodu blokowego do obsługi trybu produkcyjnego:

const autoIndex = process.env.NODE_ENV !== 'production';
mongoose.connect('mongodb://localhost/collection', { autoIndex });
Masih Jahangiri
źródło