2014-02-27 1 views
3

일부 성능 평가의 일부로 문서를 MongoDB에 추가하기 위해 반복적 인 업데이트 작업을 수행하고 있습니다. 내가 업데이트의 수에 따라 실행 시간에 큰 비선형 성을 발견했습니다 (W는 upserts /) 내가 수행하고 있습니다 :MongoDB Update-Upsert 성능 배리어 (성능이 절벽에서 떨어짐)

collection.update({'timestamp': x}, {'$set': {'value1':y, v1 : y/2, v2 : y/4}}, upsert=True) 

는 제공합니다 ...

파이썬에서 다음 명령을 반복 나 이러한 결과 ...

500 document upserts 2 seconds. 
1000 document upserts 3 seconds. 
2000 document upserts 3 seconds. 
4000 document upserts 6 seconds. 
8000 document upserts 14 seconds. 
16000 document upserts 77 seconds. 
32000 document upserts 280 seconds. 

공지 방법 8K 문서는 성능이 급격하게 저하되기 시작하고, 32K 문서 업데이트로 우리가 처리량의 6 배 감소를보고하고 업데이트 후. 왜 이런거야? "수동으로"4k 문서 업데이트를 8 번 연속해서 실행하는 것이 Python에서 모든 것을 연속적으로 수행하는 것보다 6 배 더 빠르다는 것은 이상한 것 같습니다.

mongostats에서 나는 엄청나게 높은 잠긴 db 비율 (> 100 %)을 보았고 top이 실행 중일 때 85 % 이상의 CPU 사용량을 보여주고 있습니다. VM에 4 개의 코어를 사용할 수있는 i7 프로세서가 있습니다. 이 인덱스는 고유 한 값이 포함되어야하는 경우

collection.ensure_index("timestamp") # shorthand for single-key, ascending index 

을 :

collection.ensure_index("timestamp", unique=True) 

을 사양이 인덱싱되지 않기 때문에 당신이 수행하는 업데이트입니다

+0

내가 디스크 캐싱 완벽하게 합리적인 설명은 찾을 수 계속 진행하면 성능이 떨어질 것이라고 예측합니다. 업서 트를 늘리십시오. –

+0

모음이'timestamp'에 색인되어 있습니까? – mdscruggs

+0

@mdscruggs, 현재 타임 스탬프에 대한 색인이 생성되지 않았습니다. 수동으로 선언 된 타임 스탬프로 현재 자동 생성 된 _ID를 대체 하시겠습니까? – EnemyBagJones

답변

10

당신은 당신의 "타임 스탬프"필드에 오름차순 인덱스를 넣어해야 , 데이터베이스는 콜렉션의 모든 문서를 검사하여 해당 스펙에 이미 존재하는 문서가 있는지 확인해야합니다. 500 개의 문서 (빈 컬렉션)에서이 작업을 수행하면 효과가 그렇게 나쁘지는 않지만 ... 32k에 대해 수행하면 다음과 같이됩니다 (최악의 경우) :

문서 1 - 문서 1, 갱신 또는 삽입을 확인

문서 3 발생 - - 빈 수집 가정, 확실히

문서 2를 삽입됩니다 1-2, 갱신 또는 삽입 등 ...

발생 확인 문서 ...

문서 32000 - 문서 1-3을 확인하십시오. 1999, 업데이트 또는 삽입

인덱스를 추가 할 때 데이터베이스는 더 이상 컬렉션의 모든 문서를 검사 할 필요가 없습니다. 대신 색인을 사용하여 기본 커서 대신 B- 트리 커서를 사용하여 가능한 모든 일치 항목을 훨씬 빨리 찾을 수 있습니다.

색인이 있거나없는 색인 collection.find({"timestamp": x}).explain()의 결과를 비교해야합니다 (색인을 사용하도록하려면 hint() 메서드를 사용해야 할 수도 있습니다). 중요한 요소는 얼마나 많은 문서를 반복해야하는지 ("nscanned"결과 explain()) 대 쿼리 수와 일치하는 문서 수 ("n"키)입니다. db가 일치하는 항목이나 그와 가까운 항목을 정확히 검색해야하는 경우 매우 효율적입니다. 32000 개의 항목을 스캔했지만 1 개 또는 몇 개의 일치 항목 만 찾으면 대단히 비효율적입니다. 특히 db가 각각에 대해 과 같은 작업을 수행해야하는 경우 특히 그렇습니다.

두 번 확인을위한 두드러진 주름 - update 호출에서 multi=True을 설정하지 않았으므로 일치하는 문서가 발견되면 업데이트 만하고 전체 모음을 계속 확인하지 않습니다.

링크 스팸 미안하지만,이 모두가해야-읽

http://docs.mongodb.org/manual/core/indexes/

http://api.mongodb.org/python/current/api/pymongo/collection.html#pymongo.collection.Collection.ensure_index

http://api.mongodb.org/python/current/api/pymongo/collection.html#pymongo.collection.Collection.update

http://docs.mongodb.org/manual/reference/method/cursor.explain/

+0

환상적입니다. 철저한 설명에 감사드립니다. – EnemyBagJones