저는 5 초마다 우리 집의 전력 사용량을 기록하는 오픈 소스 에너지 모니터 (http://openenergymonitor.org)를 가지고 있습니다. 그래서 MongoDB와 함께 재생하는 완벽한 응용 프로그램이라고 생각했습니다. 아파치에서 MongoEngine을 사용하여 MongoDB와의 인터페이스를 수행하는 Flask Python 애플리케이션이 있습니다.MongoDB + Python - 매우 느린 간단한 쿼리
이제는 RaspberryPi에서이 모든 것을 실행하기 때문에 놀라운 성능을 기대하지는 않지만 간단한 쿼리는 약 20 초 정도 소요됩니다.이 제한된 하드웨어에도 느려집니다. 나는 현재 지난 며칠에서 저장 약 36,000 판독이
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']
}
:
나는 다음과 같은 모델을 가지고있다. 다음 코드는 슈퍼 빠른 실행 :
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 판독이 있습니다.
나는 파이를 더 이상 기대하지 않거나 MongoDB에서 더 많은 성능을 얻기 위해 할 수있는 조정이 있습니까?
몽고가
업데이트 29/1/2014 데비안 위지에 2.1.1 : 여기 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"
}
업데이트 4 이월
좋아, 그래서 삭제 한 인덱스는, 새로운 설정 하나는 created_at에, 모든 레코드를 삭제하고 새로운 데이터를 수집하기 위해 하루 남겨 두었습니다. 난 그냥 오늘의 데이터에 대한 쿼리를 실행했는데 시간이 더 오래 (48초)에 나섭니다 : 데이터베이스에서만 16,177 기록과 하나의 인덱스입니다
> 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"
}
. 약 111MB의 여유 메모리가 있으므로 메모리에 맞는 색인에 문제가 있어서는 안됩니다. 나는이 작업을 위해 충분히 강력하지 않은 Pi로 이것을 써야 할 것 같아요.
map.hdue를 사용하여 다양한 방식으로 데이터를 집계 할 계획이므로 일일 시간을 각지도 함수에서 추출해야하기 때문에 이미 사용하고 있습니다. – littlecharva
그냥 created_at을 사용해보고, 그 값에서 날짜, 월 등을 얻는 함수를 작성하여 성능을 향상시킬 수 있습니다. 두 접근법에 시간을 할애하고 어느 것이 더 나은지를 볼 수 있습니다. 최적의 균형을 찾지 못할 수도 있습니다. .내가 언급 한 바와 같이, 필자가 언급 한 방식대로 데이터베이스 조회수를 줄이면됩니다. – Aesthete