Taşma sıralama aşaması arabelleğe alınmış veri kullanımı dahili sınırı aşıyor


85

Kodu kullanarak:

all_reviews = db_handle.find().sort('reviewDate', pymongo.ASCENDING)
print all_reviews.count()

print all_reviews[0]
print all_reviews[2000000]

Sayım yazdırılır 2043484ve yazdırılır all_reviews[0].

Ancak yazdırırken all_reviews[2000000]şu hatayı alıyorum:

pymongo.errors.OperationFailure: veritabanı hatası: Çalıştırıcı hatası: 33554495 baytlık arabelleğe alınan taşma sıralama aşaması veri kullanımı 33554432 baytlık dahili sınırı aşıyor

Bunu nasıl hallederim?

Yanıtlar:


119

Bellek içi sıralamada 32 MB sınırına giriyorsunuz:

https://docs.mongodb.com/manual/reference/limits/#Sort-Operations

Sıralama alanına bir dizin ekleyin. Bu, MongoDB'nin belgelerin tümünü sunucudaki belleğe yüklemeye ve istemciye göndermeden önce bellekte sıralamaya çalışmak yerine size sıralı sırayla akışını sağlar.


7
Bir dizin bildirmek daha iyidir, böylece RAM'de sıralamanıza gerek kalmaz: daha hızlı ve daha güvenilir, potansiyel olarak sınırsız yerine sınırlı RAM kullanımı. Israr ediyorsanız, "bul "unuzu bir toplamaya dönüştürün (sıralama için 100MB RAM kullanabilir) ve allowDiskUse: true değerini, toplama çerçevesinin 100MB RAM'i aşması durumunda diske dökülmesini söylemek için ayarlayın. Yalnızca uygun bir dizin beyan etmeye kıyasla ciddi bir performans cezası bekleyin. docs.mongodb.org/manual/reference/operator/aggregation/sort/…
A. Jesse Jiryu Davis

32
Aslında değiştirilebilir. Bu komutu çalıştırmak gerekir: db.adminCommand({setParameter: 1, internalQueryExecMaxBlockingSortBytes: <limit in bytes>}). Kaynak: askubuntu.com/questions/501937/…
kumarharsh

6
Firavun faresi kullanıcıları için, şemanızdaki pervanede indeks: true ayarının bu sorunu çözeceğini unutmamak gerekir ... firavun faresi tüm şemalarınızı gözden geçirecek ve alanların gerçekten de indeksler olduğundan emin olun, uygulamayı başlatmadan önce ... mySchema.set ('autoIndex', false) ile bu davranışı kapatırsınız;
Benjamin Conant

2
Sıralama alanında bir dizin oluşturdum, ancak yine de bu "Sıralama işlemi maksimum 33554432 bayt RAM'den daha fazla kullanıldı" hatası veriyor, sıralamadan önce eşleştirme işlemini uyguladığımdan ve sıralamadan önce eşleme kullanıyorsanız mongo belgesine göre olabilir işlem indeksi ihmal edecek ve tüm eşleşen kayıtlar üzerinde bellek sıralaması gerçekleştirecektir.
Amol Suryawanshi

11
Kabul edilen cevap buysa, o zaman bir dizinin nasıl ekleneceğine dair bilgiler içermelidir.
Philipp Ludwig

46

Tarafından söylediği gibi kumar_harshyorum bölümünde, ben başka nokta eklemek istiyorum.

adminVeritabanında aşağıdaki komutu kullanarak mevcut arabellek kullanımını görüntüleyebilirsiniz :

> use admin
switched to db admin
> db.runCommand( { getParameter : 1, "internalQueryExecMaxBlockingSortBytes" : 1 } )
{ "internalQueryExecMaxBlockingSortBytes" : 33554432, "ok" : 1 }

Varsayılan değeri 32 MB (33554432 bayt) . Bu durumda arabellek verisi sıkıntısı çekiyorsunuz, böylece kendi tanımladığınız optimum değerle arabellek sınırını artırabilirsiniz, örneğin aşağıdaki gibi 50 MB:

>  db.adminCommand({setParameter: 1, internalQueryExecMaxBlockingSortBytes:50151432})
{ "was" : 33554432, "ok" : 1 }

Bu sınırı mongodb yapılandırma dosyasında aşağıdaki parametre ile kalıcı olarak da belirleyebiliriz:

setParameter=internalQueryExecMaxBlockingSortBytes=309715200

Bu yardımcı olur umarım !!!

Note: Bu komut yalnızca sürüm 3.0 +


Yapılandırma dosyasında bu sınırı kalıcı olarak belirlemenin yolu nedir? Mongo'ya ayrılmış 1 TB'lık bir bellek makinem var ve onu kalıcı olarak çalıştırmak istiyorum.
Samantha Atkins

@SamanthaAtkins Bunu yapılandırma dosyasında kalıcı olarak ayarlamak için yanıtı güncelledim.
JERRY

@JERRY raylarda kalıcı olarak nereye ayarlanacağını. Raylar 5 / mongoid.yml?
Prateep Kul

Buldum. mongod ile terminalimde koş ve kılavuzu takip et zocada.com/setting-mongodb-users-beginners-guide
Prateep Kul

24

indeksleme ile çözüldü

db_handle.ensure_index([("reviewDate", pymongo.ASCENDING)])

seyrek bir dizin kullanmadığınızdan emin olun, her belgeyi sıralarsanız yok sayılır
Charly Koza

15

Bir dizin oluşturmaktan kaçınmak istiyorsanız (örneğin, verileri incelemek için sadece hızlı ve kirli bir kontrol istiyorsanız), disk kullanımıyla toplamayı kullanabilirsiniz:

all_reviews = db_handle.aggregate([{$sort: {'reviewDate': 1}}], {allowDiskUse: true})

(Bunu pymongo'da nasıl yapacağınızdan emin değilim).


Pymongo'da olurdu db_handle.aggregate(pipe, allowDiskUse=True). Daha fazla bilgi için bu soruya bakın !
Genarito

3

Dizin için JavaScript API sözdizimi:

db_handle.ensureIndex({executedDate: 1})

2

Benim durumumda, gerekli dizinleri kodda düzeltmek ve yeniden oluşturmak gerekliydi:

rake db:mongoid:create_indexes RAILS_ENV=production

Gerekli bir alan indeksi olduğunda bellek taşması gerçekleşmediğinden.

PS Bundan önce, uzun dizinler oluştururken hataları devre dışı bırakmak zorunda kaldım:

# mongo
MongoDB shell version: 2.6.12
connecting to: test
> db.getSiblingDB('admin').runCommand( { setParameter: 1, failIndexKeyTooLong: false } )

Ayrıca gerekli olabilir reIndex:

# mongo
MongoDB shell version: 2.6.12
connecting to: test
> use your_db
switched to db your_db
> db.getCollectionNames().forEach( function(collection){ db[collection].reIndex() } )
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.