2012-05-31 3 views
0

현재 약 43,000,000 개 요소의 전체 몽고 컬렉션을 거쳐 오랜 기간 실행되는 (Python + Celery에서 실행되는) 작업이 있으며 해당 요소를 변경하지 않고 요소에 대한 분석을 수행합니다 .스플릿 몽고 컬렉션 (인덱스로)

이 컬렉션이 늘어남에 따라 작업이 더 길어지기 시작했으며 (이제) 다른 데이터베이스에 대한 시간 초과로 인해 일반적으로 주기적으로 실패합니다.

이 작업을 여러 개의 작은 작업으로 나눠보고 싶습니다. 아마도 몇 백만 개의 요소로 작동 할 것입니다. 그리고 분할 작업을 수행 할 쿼리를 만드는 가장 좋은 방법에 대해 궁금합니다. 이 컬렉션에는 하나의 색인과 _id 만 있습니다.

확실한 대답은 뭔가처럼 될 듯 :

# This is executed in parallel on different servers 
def doAnalysis(skipped,limit) 
    db.<collection>.find().skip(skipped).limit(limit) 

... 

# This is the parent task 
elemsToAnalyze = db.<collection>.find().count()/10; 
for i in range(0,10: 
    doAnalysis(elemsToAnalyze * i, elemsToAnalyze) 

하지만 그것은 .skip() 시간이 소요 밝혀 - 기본적으로 그냥만큼 실제로 분석을 수행! 이 작업을 수행하는 더 좋은 방법이 있습니까?

답변

1

skip()은 이러한 경우에 매우 느릴 수 있습니다. 배치의 마지막 _id을 사용하여 범위 쿼리를 수행하여 다음 배치를 쿼리 할 수 ​​있습니다. 이런 식으로 :

db.<collection>.find({ "_id" : { $gte: prev_batch_last_id } }).sort({ _id : 1 }).limit(limit); 

변수의 마지막 ID는 직접 변수에 저장해야합니다.

+0

답장을 보내 주셔서 감사합니다. 이 방법의 문제점은 * 이전에 실행 된 * 배치에서 last_id를 알아야한다는 것입니다. 데이터를 공유 할 필요가 없도록 이러한 프로세스를 독립적으로 실행할 수 있어야합니다. 병렬 처리가 가능하다는 이점이 있습니다. –

+0

이 컬렉션은 조각입니까? 그렇다면 컬렉션을 분할하는 방법으로 청크 경계를 사용할 수 있습니다. 그렇지 않은 경우 컬렉션에 _id의 범위를 분할하는 다른 방법이 있습니다. – matulef

+0

@ChrisW 샘플 코드를 기반으로 병렬 처리가 필요 없다고 생각했습니다. 여러 데이터베이스가 있습니까? matulef가 언급했듯이 sharding 경계를 사용할 수 있습니다 (sharded 경우). 각 요소에 대해 수행하는 작업이 매우 짧은 경우, db가 한 번에 하나의 쿼리 만 처리 할 수 ​​있기 때문에 하나의 db에 대해 병렬로 쿼리를 수행하면 처리 속도가 향상되지 않을 수도 있습니다. 병렬 방식이 실제로 더 빠르거나 빠르면 먼저 (수동으로) 시도 할 수 있습니다. – Lycha