我有一個開源的能源監視器(http://openenergymonitor.org),它每五秒記錄我家的用電量,所以我認爲這將是一個完美的應用程序,可以與MongoDB一起玩。我有一個使用MongoEngine與MongoDB進行交互的Flask Python應用程序。MongoDB + Python - 非常慢的簡單查詢
現在我正在RaspberryPi上運行所有這些,所以我並不期待令人難以置信的性能,但一個簡單的查詢花費了大約20秒,這對於這個有限的硬件來說似乎很慢。
我有以下型號:
class Reading(db.Document):
created_at = db.DateTimeField(default=datetime.datetime.now, required=True)
created_at_year = db.IntField(default=datetime.datetime.now().year, required=True)
created_at_month = db.IntField(default=datetime.datetime.now().month, required=True)
created_at_day = db.IntField(default=datetime.datetime.now().day, required=True)
created_at_hour = db.IntField(default=datetime.datetime.now().hour, required=True)
battery = db.IntField()
power = db.IntField()
meta = {
'indexes': ['created_at_year', 'created_at_month', 'created_at_day', 'created_at_hour']
}
我目前已經從過去幾天的存儲各地36000讀數。下面的代碼運行超快:
def get_readings_count():
count = '<p>Count: %d</p>' % Reading.objects.count()
return count
def get_last_24_readings_as_json():
readings = Reading.objects.order_by('-id')[:24]
result = "["
for reading in reversed(readings):
result += str(reading.power) + ","
result = result[:-1]
result += "]"
return result
但做一個簡單的過濾器:
def get_today_readings_count():
todaycount = '<p>Today: %d</p>' % Reading.objects(created_at_year=2014, created_at_month=1, created_at_day=28).count()
return todaycount
需要超過20秒 - 有大約爲11,000讀數今天。
我應該放棄期待更多我的Pi,還是有一些調整我可以做到從MongoDB獲得更多的性能?
蒙戈2.1.1在Debian喘息
更新29/1/2014:
針對下面的答案,這裏是getIndexes的結果(上)並解釋():
> db.reading.getIndexes()
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"ns" : "sensor_network.reading",
"name" : "_id_"
},
{
"v" : 1,
"key" : {
"created_at_year" : 1
},
"ns" : "sensor_network.reading",
"name" : "created_at_year_1",
"background" : false,
"dropDups" : false
},
{
"v" : 1,
"key" : {
"created_at_month" : 1
},
"ns" : "sensor_network.reading",
"name" : "created_at_month_1",
"background" : false,
"dropDups" : false
},
{
"v" : 1,
"key" : {
"created_at_day" : 1
},
"ns" : "sensor_network.reading",
"name" : "created_at_day_1",
"background" : false,
"dropDups" : false
},
{
"v" : 1,
"key" : {
"created_at_hour" : 1
},
"ns" : "sensor_network.reading",
"name" : "created_at_hour_1",
"background" : false,
"dropDups" : false
}
]
> db.reading.find({created_at_year: 2014, created_at_month: 1, created_at_day: 28 }).explain()
{
"cursor" : "BtreeCursor created_at_day_1",
"isMultiKey" : false,
"n" : 15689,
"nscannedObjects" : 15994,
"nscanned" : 15994,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 5,
"nChunkSkips" : 0,
"millis" : 25511,
"indexBounds" : {
"created_at_day" : [
[
28,
28
]
]
},
"server" : "raspberrypi:27017"
}
更新2月4日
好了,所以我刪除索引,樹立了新的一個關於created_at,刪除所有的記錄,並留下一天收集新的數據。我剛剛運行當今數據的查詢,它需要較長的時間(48秒):
> db.reading.find({'created_at': {'$gte':ISODate("2014-02-04")}}).explain()
{
"cursor" : "BtreeCursor created_at_1",
"isMultiKey" : false,
"n" : 14189,
"nscannedObjects" : 14189,
"nscanned" : 14189,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 9,
"nChunkSkips" : 0,
"millis" : 48653,
"indexBounds" : {
"created_at" : [
[
ISODate("2014-02-04T00:00:00Z"),
ISODate("292278995-12-2147483314T07:12:56.808Z")
]
]
},
"server" : "raspberrypi:27017"
}
與僅16177數據庫中的記錄,只有一個指標的。大約有111MB的可用內存,因此內存中的索引擬合應該沒有問題。我想我將不得不寫這篇文章,因爲Pi沒有足夠強大的工作。
我將日期時間分解爲其組成部分,因爲我打算用mapreduce以各種方式聚合數據,而不是必須在每個地圖功能中提取日期或小時,它已經在那裏供我使用。 – littlecharva
嘗試並使用created_at,並編寫函數以從該值中獲取日期,月份等,這樣做可以提高性能,您可以計時兩種方法並查看哪種方法更好,您可能偶然發現最佳平衡 。我還應該補充一下,按照提到的方式,要求的數據庫命中次數少於完成的方式 – Aesthete