일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 김양재 목사님
- 데이터 과학
- openCV
- Statistics
- c++
- 빅데이터
- 빅 데이터
- 김양재
- Artificial Intelligence
- Big Data
- data science
- 몽고디비
- probability
- nodeJS
- 인공지능
- 우리들교회
- MongoDB
- Deep learning
- 주일설교
- WebGL
- 확률
- No SQL
- Machine Learning
- 빅데이타
- 통계
- 딥러닝
- 빅 데이타
- node.js
- R
- 김양재 목사
- Today
- Total
Scientific Computing & Data Science
[MongoDB] Query / skip 속도 높이기 본문
Written by cinema4d
앞서 "Cursors"를 다룬 글에서 도큐먼트 쿼리 시 "skip"을 통해 도큐먼트를 건너뛰는 것에 대해 알아본 바 있다.
"skip" 연산자는 작은 규모의 도큐먼트에 대해서는 적당할 지 모르지만, 도큐먼트 규모가 커지면 건너뛰는 속도가 현저히 떨어진다. 이것은 MongoDB만의 문제가 아닌 거의 모든 데이터베이스에서 공통적으로 나타나는 현상이다.
따라서, 큰 규모의 도큐먼트에서 도큐먼트를 건너뛰어 검색 결과를 받아올 때 "skip"은 반드시 피해야 한다.
skip 없이 결과 표시하기
다음과 같이 1 ~ 30000까지의 "cnt" 값을 가지는 도큐먼트를 생성해 보자:
for(i=1; i<30001; i++) {
db.count.insert({cnt : i});
}
만약 20000개의 도큐먼트를 건너뛰려면
var myCursor = db.count.find().skip(20000);
대신 다음과 같이 "$gt" 연산자를 사용하는 것이 훨씬 빠른 속도를 보일 것이다(상황에 따라 속도차이를 거의 못 느낄 수도 있다.)
> var myCursor = db.count.find({cnt: {$gt: 20000}}); > myCursor { "_id" : ObjectId("52f38fff2d911bccacf26913"), "cnt" : 20001 } { "_id" : ObjectId("52f38fff2d911bccacf26914"), "cnt" : 20002 } { "_id" : ObjectId("52f38fff2d911bccacf26915"), "cnt" : 20003 } { "_id" : ObjectId("52f38fff2d911bccacf26916"), "cnt" : 20004 } { "_id" : ObjectId("52f38fff2d911bccacf26917"), "cnt" : 20005 } { "_id" : ObjectId("52f38fff2d911bccacf26918"), "cnt" : 20006 } { "_id" : ObjectId("52f38fff2d911bccacf26919"), "cnt" : 20007 } { "_id" : ObjectId("52f38fff2d911bccacf2691a"), "cnt" : 20008 } { "_id" : ObjectId("52f38fff2d911bccacf2691b"), "cnt" : 20009 } { "_id" : ObjectId("52f38fff2d911bccacf2691c"), "cnt" : 20010 } { "_id" : ObjectId("52f38fff2d911bccacf2691d"), "cnt" : 20011 } { "_id" : ObjectId("52f38fff2d911bccacf2691e"), "cnt" : 20012 } { "_id" : ObjectId("52f38fff2d911bccacf2691f"), "cnt" : 20013 } { "_id" : ObjectId("52f38fff2d911bccacf26920"), "cnt" : 20014 } { "_id" : ObjectId("52f38fff2d911bccacf26921"), "cnt" : 20015 } { "_id" : ObjectId("52f38fff2d911bccacf26922"), "cnt" : 20016 } { "_id" : ObjectId("52f38fff2d911bccacf26923"), "cnt" : 20017 } { "_id" : ObjectId("52f38fff2d911bccacf26924"), "cnt" : 20018 } { "_id" : ObjectId("52f38fff2d911bccacf26925"), "cnt" : 20019 } { "_id" : ObjectId("52f38fff2d911bccacf26926"), "cnt" : 20020 } Type "it" for more
랜덤 도큐먼트 검색하기
컬렉션으로부터 랜덤 도큐먼트를 얻는 방법 중 가장 단순하면서도 무식한(?) 방법은 전체 도큐먼트 수를 파악하고 이 범위 안에서 랜덤 수를 발생시켜 그 수만큼 도큐먼트를 "skip"하는 것이다. 다음 예를 살펴보자.
for(i=1; i<1001; i++) {
db.myCollection.insert({cnt : i});
}
var total = db.myCollection.count();
var random = Math.floor(Math.random()*total);
db.myCollection.find().skip(random).limit(1);
위의 코드는 1000개의 도큐먼트를 생성하고, 도큐먼트의 전체 개수를 파악하여 전체 개수의 범위에 대한 랜덤 수를 발생시킨 후, 그 수만큼 "skip"한 후 1개의 도큐먼트를 얻어왔다.
그러나, 이 방법은 도큐먼트 수가 매우 많을 때에는 속도가 현저히 느려지므로 좋은 방법이 아니다. 일반적으로 사용하는 랜덤 도큐먼트 검색은 약간의 트릭이 숨어있다.
위의 myCollection에는 키(key) 값이 "cnt" 뿐인데, 각 도큐먼트에 랜덤 번호를 추가하여, 랜덤 수를 발생하여 그 수보다 작거나 큰 하나의 도큐먼트를 찾는 방법이 훨씬 효율적이다.
다음 예를 통해 보다 효율적인 "skip" 방법을 알아보자.
// myCollection에 "random" 키를 설정하고 랜덤수를 저장한다.
for(i=1; i<1001; i++) {
db.myCollection.update({cnt: i}, {$addToSet: {random: Math.random()}});
}
// 랜덤수를 하나 발생시키고 그 값보다 큰 도큐먼트 1개를 찾는다.
var myRandom = Math.random();
result = db.myCollection.findOne({random : {$gt : myRandom}});
// 만약 "result"에 아무값도 저장되지 않으면, 발생된 랜덤수보다 작은 도큐먼트 1개를 찾는다.
if (result == null) {
result = db.myCollection.findOne({random : {$lt : random}});
}
라인 10 - 13의 설명은 다음과 같다: 랜덤수를 하나 발생시키고 그 값보다 큰 도큐먼트 1개를 찾는 경우, 발생된 랜덤수보다 큰 "random" 값을 가지고 있는 도큐먼트가 없을 확률도 있다.
이를 방지하기 위해 "result"에 아무 값도 저장되어 있지 않다면(result == null) 좀전에 발생한 랜덤수보다 작은 도큐먼트 1개를 찾는다.
'Data Science > MongoDB' 카테고리의 다른 글
[MongoDB] Query / $snapshot (0) | 2014.02.09 |
---|---|
[MongoDB] Query / Other Query Operations (0) | 2014.02.08 |
[MongoDB] Query / Cursors (0) | 2014.02.06 |
[MongoDB] Query / $where (0) | 2014.02.04 |
[MongoDB] Query / Querying Embedded Documents (0) | 2014.02.02 |