2011-08-29 12 views
46

Mam ponad 300 000 rekordów w jednej kolekcji w Mongo.Powolne dzielenie stron na tony rekordów w mongodb

Kiedy uruchomić to bardzo proste zapytanie:

db.myCollection.find().limit(5); 

To trwa tylko kilka milisekund.

Ale gdy używam pominąć w zapytaniu:

db.myCollection.find().skip(200000).limit(5) 

To niczego nie powrócić ... biegnie przez kilka minut i nic nie zwraca.

Jak zrobić to lepiej?

Odpowiedz

57

Od MongoDB documentation:

Koszty przywoławcze

Niestety pominąć może być (bardzo) kosztowne i wymaga, aby serwer do chodzenia od początku zbierania lub indeksu, aby dostać się do Przesunięcie/pomijanie pozycji, zanim będzie można rozpocząć zwracanie strony danych (limit). Wraz ze wzrostem liczby stron, pomijanie będzie wolniejsze i bardziej intensywne cpu, i prawdopodobnie powiązane z IO, z większymi kolekcjami.

Strony oparte na zasięgach zapewniają lepsze wykorzystanie indeksów, ale nie pozwalają na łatwe przejście do określonej strony.

Musisz zadać sobie pytanie: jak często potrzebujesz 40000 strony? Zobacz także artykuł this;

78

Jedno podejście do tego problemu, jeśli masz duże ilości dokumentów i pokazujemy je w klasyfikowane porządek (nie jestem pewien, jak użyteczny skip jest jeśli nie jesteś) byłoby użyć klucza, który "ponowne sortowanie w celu wybrania następnej strony wyników.

Więc jeśli zaczniesz z

db.myCollection.find().limit(100).sort({created_date:true}); 

a następnie wyodrębnić daty utworzenia ostatniego dokumentu zwróconego przez kursor do zmiennej max_created_date_from_last_result, można uzyskać kolejną stronę z dużo bardziej wydajne (zakładając, masz indeks na created_date) zapytanie

db.myCollection.find({created_date : { $gt : max_created_date_from_last_result } }).limit(100).sort({created_date:true}); 
+3

Wydaje się to naprawdę dobre. Dlaczego nie widzę więcej osób, które to sugerują? – steve

+3

Ograniczenie polega na tym, że można przesuwać się tylko o jedną stronę w przód lub wstecz, zamiast przeskakiwać do określonej strony, ale w przypadku ograniczonego użycia uważam, że działa dobrze. – Russell

+0

Fajny pomysł. Jeśli naprawdę nie zależy ci na sortowaniu (innym niż do tego celu) i nie chcesz sortować ani tworzyć indeksu, wydaje się, że możesz pominąć krok i skorzystać z pola ObjectId (_id), które będzie być indeksowane ... możliwe, że identyfikatory obiektów zostaną poddane recyklingowi, ale znowu nie ma to znaczenia w tym przypadku. – jsh