집계 프레임워크의 $198 및 $제한
문서를 읽었을 때 다음과 같은 참고 사항을 발견했습니다.
$sort가 파이프라인의 $limit 바로 앞에 있는 경우 $sort 작업은 진행됨에 따라 상위 n개의 결과만 유지합니다. 여기서 n은 지정된 제한이며 MongoDB는 메모리에 항목을 저장하기만 하면 됩니다.이 최적화는 allowDiskUse가 참이고 항목이 집계 메모리 제한을 초과하는 경우에도 적용됩니다.
만약 내가 이것에 대해 옳다면, $sort와 $limit을 같이 사용할 때만 적용됩니다.
db.coll.aggregate([
...,
{$sort: ...},
{$limit: limit},
...
]);
하지만, 대부분의 시간을 우리가 가질 것이라고 생각합니다.
db.coll.aggregate([
...,
{$sort: ...},
{$skip: skip},
{$limit: limit},
...
]);
질문 1: $skip를 여기서 사용하면 위의 규칙이 적용되지 않는다는 뜻입니까?
이론적으로 MongoDB는 여전히 상위 n개의 레코드를 계산할 수 있고 상위 n개의 레코드만 정렬하여 성능을 향상시킬 수 있기 때문에 이 질문을 합니다.하지만 저는 이것에 대한 어떤 문서도 찾지 못했습니다.만약 규칙이 적용되지 않는다면,
질문 2: 성능을 향상시키려면 쿼리를 다음으로 변경해야 합니까?
db.coll.aggregate([
...,
{$sort: ...},
{$limit: skip + limit},
{$skip: skip},
{$limit: limit},
...
]);
편집: 제 사용 사례를 설명하면 위의 질문이 더 타당할 것 같습니다.MongoDB 2.6에서 제공하는 텍스트 검색 기능을 사용하여 제품을 찾고 있습니다.사용자가 "빨간색"과 같은 매우 일반적인 키워드를 입력하면 결과가 너무 많이 반환되지 않을까 걱정됩니다.따라서 저는 이 결과를 생성할 수 있는 더 나은 방법을 찾고 있습니다.
EDIT2: 위의 마지막 코드는 다음과 같습니다.
db.coll.aggregate([
...,
{$sort: ...},
{$limit: skip + limit},
{$skip: skip},
...
]);
따라서 항상 이 양식을 사용하여 상위 N 규칙을 적용할 수 있습니다.
이것은 텍스트 검색 쿼리이므로 가장 적합한 형식은 다음과 같습니다.
db.collection.aggregate([
{
"$match": {
"$text": { "$search": "cake tea" }
}
},
{ "$sort": { "score": { "$meta": "textScore" } } },
{ "$limit": skip + limit },
{ "$skip": skip }
])
상위 "정렬" 결과의 메모리 예약에 대한 근거는 원래대로 자신의 "한계" 내에서만 작동하며, 이는 데이터의 몇 개의 합리적인 "페이지"를 초과하는 어떤 것에도 최적화되지 않습니다.
메모리 소비에 합리적인 수준을 넘어서면 추가 단계는 긍정적이기보다는 부정적인 영향을 미칠 가능성이 높습니다.
이것들은 실제로 현재 형태의 MongoDB에서 사용할 수 있는 텍스트 검색 기능의 실질적인 한계입니다.그러나 보다 세부적이고 성능이 더 요구되는 경우에는 대부분의 SQL "전체 텍스트" 솔루션과 마찬가지로 외부 "목적에 맞게 구축된" 텍스트 검색 솔루션을 사용하는 것이 좋습니다.
답변: $limit 앞에서 $skip
적어도 집계의 경우 $skip과 $limit의 순서는 확실히 중요합니다.그냥 해봤는데, 어떻게 빠졌는지 모르겠어요, 작전 이후로 바뀌었을 수도 있지만 공유하려고 생각했어요.
저는 이 대화에서 @vkarpov15의 의견에 동의합니다.
전체적으로 $limit은 다음 집계 상태로 전송되는 문서 수를 제한하고 $limit은 첫 번째 N개 문서를 건너뜁니다. 따라서 $limit이 $limit 이후이고 $limit > = $limit이면 결과를 얻을 수 없습니다.간단히 말해서, 이것은 MongoDB에서 예상되는 동작입니다.
제가 발견한 바에 따르면 이 사건은limit
그리고.skip
중요하지 않습니다.를 skip
앞에limit
는 DB를 만들 입니다.limit
앞에skip
후드 밑에
> db.system.profile.find().limit(1).sort( { ts : -1 } ).pretty()
{
"op" : "command",
"ns" : "archiprod.userinfos",
"command" : {
"aggregate" : "userinfos",
"pipeline" : [
{
"$sort" : {
"updatedAt" : -1
}
},
{
"$limit" : 625
},
{
"$skip" : 600
}
],
},
"keysExamined" : 625,
"docsExamined" : 625,
"cursorExhausted" : true,
"numYield" : 4,
"nreturned" : 25,
"millis" : 25,
"planSummary" : "IXSCAN { updatedAt: -1 }",
/* Some fields are omitted */
}
제가 를 켜면 요?$skip
그리고.$limit
도 같은 결과를 얻었습니다.keysExamined
그리고.docsExamined
.
> db.system.profile.find().limit(1).sort( { ts : -1 } ).pretty()
{
"op" : "command",
"ns" : "archiprod.userinfos",
"command" : {
"aggregate" : "userinfos",
"pipeline" : [
{
"$sort" : {
"updatedAt" : -1
}
},
{
"$skip" : 600
},
{
"$limit" : 25
}
],
},
"keysExamined" : 625,
"docsExamined" : 625,
"cursorExhausted" : true,
"numYield" : 5,
"nreturned" : 25,
"millis" : 71,
"planSummary" : "IXSCAN { updatedAt: -1 }",
}
그리고 나서 저는 질문의 설명 결과를 확인했습니다.나는 그것을 발견했습니다.totalDocsExamined
미입니다.625
에 시대에limit
무대.
> db.userinfos.explain('executionStats').aggregate([ { "$sort" : { "updatedAt" : -1 } }, { "$limit" : 625 }, { "$skip" : 600 } ])
{
"stages" : [
{
"$cursor" : {
"sort" : {
"updatedAt" : -1
},
"limit" : NumberLong(625),
"queryPlanner" : {
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"updatedAt" : -1
},
"indexName" : "updatedAt_-1",
}
},
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 625,
"executionTimeMillis" : 22,
"totalKeysExamined" : 625,
"totalDocsExamined" : 625,
"executionStages" : {
"stage" : "FETCH",
"nReturned" : 625,
"executionTimeMillisEstimate" : 0,
"works" : 625,
"advanced" : 625,
"docsExamined" : 625,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 625,
"works" : 625,
"advanced" : 625,
"keyPattern" : {
"updatedAt" : -1
},
"indexName" : "updatedAt_-1",
"keysExamined" : 625,
}
}
}
}
},
{
"$skip" : NumberLong(600)
}
]
}
그리고 놀랍게도, 저는 그것을 바꾸는 것을 발견했습니다.$skip
그리고.$limit
같은 결과를 낳습니다.explain
결과.
> db.userinfos.explain('executionStats').aggregate([ { "$sort" : { "updatedAt" : -1 } }, { "$skip" : 600 }, { "$limit" : 25 } ])
{
"stages" : [
{
"$cursor" : {
"sort" : {
"updatedAt" : -1
},
"limit" : NumberLong(625),
"queryPlanner" : {
/* Omitted */
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 625,
"executionTimeMillis" : 31,
"totalKeysExamined" : 625,
"totalDocsExamined" : 625,
/* Omitted */
}
}
},
{
"$skip" : NumberLong(600)
}
]
}
보시다시피, 제가 지정한 것은$skip
앞에$limit
에서, 서에explain
결과는 여전히$limit
앞에$skip
.
간단히 말해서, 저는 그것이 중요하지 않다는 결론에 도달했습니다.쿼리에 필터가 없다고 가정하고, 먼저 10개의 문서를 건너뛴 다음 5개의 문서로 제한합니다. 설명이 있으면 쿼리는 마지막 5개의 문서를 반환하고 총 15개의 문서를 검사합니다.제 분석을 판단해 주세요.
언급URL : https://stackoverflow.com/questions/24160037/skip-and-limit-in-aggregation-framework
'programing' 카테고리의 다른 글
배치 파일에서 어떤 주석 스타일을 사용해야 합니까? (0) | 2023.05.04 |
---|---|
셸에서 문자열의 마지막 문자를 가져오는 방법은 무엇입니까? (0) | 2023.05.04 |
Azure 함수에서 간단한 방법으로 GET 쿼리 매개 변수를 가져오는 방법은 무엇입니까? (0) | 2023.05.04 |
Angular에서 사용자 지정 테마 팔레트를 사용하려면 어떻게 해야 합니까? (0) | 2023.05.04 |
Angular zone 외부에서 트리거된 탐색입니다. 'ngZone.run()'을 호출하는 것을 잊으셨습니까? (0) | 2023.05.04 |