Amazon DocumentDB에서 쿼리
이 섹션에서는 Amazon DocumentDB를 사용한 쿼리의 모든 측면을 설명합니다.
문서 쿼리
이따금 판매하는 물품을 고객이 보고 구매할 수 있도록 온라인 상점의 재고를 조회해야 할 수도 있습니다. 컬렉션을 쿼리하는 것은 컬렉션의 모든 문서에 대한 것이든 특정 기준을 충족하는 문서에만 대한 것이든 관계없이 상대적으로 간단합니다.
문서를 쿼리하려면 find()
작업을 사용합니다. find()
명령에는 반환할 문서 선택 시 사용할 기준을 정의하는 단일 문서 파라미터가 있습니다. find()
의 출력은 줄 바꿈이 없이 한 줄로 된 텍스트 형식의 문서입니다. 쉽게 읽기 위해 출력 문서의 형식을 지정하려면 find().pretty()
를 사용하십시오. 이 주제의 모든 예제는 .pretty()
를 사용하여 출력 형식을 지정합니다.
다음 코드 샘플은 이전 두 연습에서 example
컬렉션에 삽입한 문서 4개를 사용합니다. insertOne()
및 insertMany()
는 문서 작업의 문서 추가 섹션에 있습니다.
컬렉션의 모든 문서 검색
모음의 모든 문서를 검색하려면 빈 쿼리 문서로 find()
작업을 사용하십시오.
다음 쿼리는 example
모음의 모든 문서를 반환합니다.
db.example.find( {} ).pretty()
피드 값과 일치하는 문서 검색
필드 및 값과 일치하는 모든 문서를 검색하려면 일치하는 필드 및 값을 식별하는 쿼리 문서로 find()
작업을 사용합니다.
이전 문서를 사용하면 이 쿼리는 "Item" 필드가 "Pen"과 동일한 모든 문서를 반환합니다.
db.example.find( { "Item": "Pen" } ).pretty()
내장 문서와 일치하는 문서 검색
내장 문서와 일치하는 모든 문서를 찾으려면 내장 문서 이름과 내장 문서의 모든 필드 및 값을 지정하는 쿼리 문서와 함께 find()
작업을 사용합니다.
내장 문서를 일치시킬 때 문서의 내장 문서는 쿼리에 있는 것과 동일한 이름을 가져야 합니다. 또한, 내장 문서의 필드 및 값은 쿼리와 일치해야 합니다.
다음 쿼리는 "Poster Paint" 문서만 반환합니다. "Pen"에는 "OnHand
" 및 "MinOnHand
"에 대한 다른 값이 있으며, "Spray Paint"에는 쿼리 문서보다 필드 하나(OrderQnty
)가 더 있기 때문입니다.
db.example.find({"Inventory": { "OnHand": 47, "MinOnHand": 50 } } ).pretty()
내장 문서의 필드 값과 일치하는 문서 검색
내장 문서와 일치하는 모든 문서를 찾으려면 내장 문서 이름과 내장 문서의 모든 필드 및 값을 지정하는 쿼리 문서와 함께 find()
작업을 사용합니다.
이전 문서에서 다음 쿼리는 "점 표기법"을 사용하여 내장 문서와 관심 있는 필드를 지정합니다. 다른 필드가 내장 문서에 표시될 수 있는지 여부와 무관하게 이와 일치하는 모든 문서가 반환됩니다. "Poster Paint" 및 "Spray Paint"가 지정된 필드 및 값과 일치하므로 쿼리가 "Poster Paint" 및 "Spray Paint"를 반환합니다.
db.example.find({"Inventory.OnHand": 47, "Inventory.MinOnHand": 50 }).pretty()
배열이 일치하는 문서 검색
배열이 일치하는 모든 문서를 찾으려면 관심 있는 배열 이름과 해당 배열의 모든 값을 포함하여 find()
작업을 사용합니다. 쿼리가 배열 값이 동일하면서 쿼리와 동일한 순서인 해당 이름을 가진 배열을 포함한 모든 문서를 반환합니다.
"Poster Paint"에는 추가 색상(White)이 있고 "Spray Paint"에는 색상이 다른 순서로 있으므로 다음 쿼리는 "Pen"만을 반환합니다.
db.example.find( { "Colors": ["Red","Green","Blue","Black"] } ).pretty()
배열의 값과 일치하는 문서 검색
특정 배열 값을 보유한 모든 문서를 찾으려면 관심 있는 배열 이름과 값을 포함하여 find()
작업을 사용합니다.
db.example.find( { "Colors": "Red" } ).pretty()
각각 Colors
라는 배열과 배열 내에 "Red
" 값이 있으므로 이전 작업은 세 문서 모두를 반환합니다. "White
" 값을 지정한 경우 쿼리는 "Poster Paint"만 반환합니다.
연산자를 사용하여 문서 검색
다음 쿼리는 "Inventory.OnHand
" 값이 50 미만인 모든 문서를 반환합니다.
db.example.find( { "Inventory.OnHand": { $lt: 50 } } )
지원되는 쿼리 연산자 목록은 쿼리 및 프로젝션 연산자 섹션을 참조하십시오.
쿼리 계획
쿼리 계획에 대한 executionStats
를 보려면 어떻게 해야 합니까?
쿼리가 예상보다 느리게 실행되는 이유를 결정할 때 쿼리 계획에 대한 executionStats
가 무엇인지 이해하는 것이 유용할 수 있습니다. executionStats
에서는 특정 단계에서 반환된 문서 수(nReturned
), 각 단계에서 소요된 실행 시간(executionTimeMillisEstimate
) 및 쿼리 계획을 생성하는 데 걸리는 시간(planningTimeMillis
)을 제공합니다. 아래 쿼리 예제와 같이 가장 시간이 많이 걸리는 쿼리 단계를 결정하여 executionStats
의 출력에서 최적화 작업에 집중할 수 있습니다. executionStats
파라미터는 현재 update
및 delete
명령을 지원하지 않습니다.
참고
Amazon DocumentDB는 분산, 내결함성, 자가 치유 스토리지 시스템을 활용하는 목적으로 만들어진 데이터베이스 엔진에서 MongoDB 3.6 API를 에뮬레이션합니다. 그 결과, 쿼리 계획과 explain()
의 출력은 Amazon DocumentDB와 MongoDB 간에 다를 수 있습니다. 쿼리 계획을 제어하려는 고객은 $hint
연산자를 사용하여 기본 인덱스를 선택할 수 있습니다.
다음과 같이 explain()
명령에서 개선하려는 쿼리를 실행합니다.
db.runCommand({explain: {query document}}). explain("executionStats").executionStats;
예는 다음과 같습니다.
db.fish.find({}).limit(2).explain("executionStats");
이 작업의 출력은 다음과 같이 표시됩니다.
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test.fish",
"winningPlan" : {
"stage" : "SUBSCAN",
"inputStage" : {
"stage" : "LIMIT_SKIP",
"inputStage" : {
"stage" : "COLLSCAN"
}
}
}
},
"executionStats" : {
"executionSuccess" : true,
"executionTimeMillis" : "0.063",
"planningTimeMillis" : "0.040",
"executionStages" : {
"stage" : "SUBSCAN",
"nReturned" : "2",
"executionTimeMillisEstimate" : "0.012",
"inputStage" : {
"stage" : "LIMIT_SKIP",
"nReturned" : "2",
"executionTimeMillisEstimate" : "0.005",
"inputStage" : {
"stage" : "COLLSCAN",
"nReturned" : "2",
"executionTimeMillisEstimate" : "0.005"
}
}
}
},
"serverInfo" : {
"host" : "enginedemo",
"port" : 27017,
"version" : "3.6.0"
},
"ok" : 1
}
위의 쿼리에서 executionStats
만 보는 데 관심이 있다면 다음 명령을 사용할 수 있습니다. 작은 컬렉션에서는 성능 이득이 무시할 수준인 경우 Amazon DocumentDB 쿼리 프로세서는 인덱스를 사용하지 않도록 결정할 수 있습니다.
db.fish.find({}).limit(2).explain("executionStats").executionStats;
쿼리 계획 캐시
성능을 최적화하고 계획 기간을 줄이기 위해 Amazon DocumentDB는 쿼리 계획을 내부적으로 캐싱합니다. 이렇게 하면 캐시된 계획을 사용하여 동일한 모양의 쿼리를 직접 실행할 수 있습니다.
하지만 이 캐싱으로 인해 동일한 쿼리에 대해 무작위 지연이 발생할 수 있습니다. 예를 들어 쿼리를 실행하는 데 보통 1초가 걸리는 경우 가끔 10초가 걸릴 수 있습니다. 이는 시간이 지나면서 reader 인스턴스가 다양한 형태의 쿼리를 캐시하여 메모리를 소비하기 때문입니다. 이러한 무작위 속도 저하가 발생하는 경우 메모리를 해제하기 위해 별도의 조치를 취하지 않아도 됩니다. 시스템에서 자동으로 메모리 사용량을 관리하고 메모리가 특정 임계값에 도달하면 자동으로 해제됩니다.
결과의 설명
쿼리 계획에 대한 정보를 반환하려는 경우 Amazon DocumentDB는 세부 정보 표시 모드 queryPlanner
를 지원합니다. explain
결과는 옵티마이저가 선택한 쿼리 계획을 다음과 비슷한 형식으로 반환합니다.
{ "queryPlanner" : { "plannerVersion" : <int>, "namespace" : <string>, "winningPlan" : { "stage" : <STAGE1>, ... "inputStage" : { "stage" : <STAGE2>, ... "inputStage" : { ... } } } } }
다음 섹션에서는 일반적인 explain
결과를 정의합니다.
스캔 및 필터 단계
옵티마이저는 다음 스캔 중 하나를 선택할 수 있습니다.
콜스캔
이 단계는 순차적 수집 스캔입니다.
{ "stage" : "COLLSCAN" }
ISSCAN
이 단계에서는 인덱스 키를 스캔합니다. 옵티마이저는 이 단계 내 문서를 검색할 수 있으며, 이 경우 나중에 FETCH 단계가 추가될 수 있습니다.
db.foo.find({"a": 1}) { "stage" : "IXSCAN", "direction" : "forward", "indexName" : <idx_name> }
FETCH
옵티마이저가 IXSCAN 이외의 단계에서 문서를 검색한 경우 결과에는 FETCH 단계가 포함됩니다. 예를 들어, 위의 IXSCAN 쿼리는 FETCH와 IXSCAN 단계가 조합된 결과를 초래할 수 있습니다.
db.foo.find({"a": 1}) { "stage" : "FETCH", "inputStage" : { "stage" : "IXSCAN", "indexName" : <idx_name> } }
IXONLYSCAN은 인덱스 키만 스캔합니다. 복합 인덱스를 생성해도 FETCH를 피할 수는 없습니다.
인덱스 교집합
아일랜드
Amazon DocumentDB에는 인덱스 교차를 활용할 수 있는 경우 IXScan의 InputStage 배열이 포함된 IXAND 스테이지가 포함될 수 있습니다. 예를 들어 다음과 같은 출력이 표시될 수 있습니다.
{ "stage" : "FETCH", "inputStage" : { "stage" : "IXAND", "inputStages" : [ { "stage" : "IXSCAN", "indexName" : "a_1" }, { "stage" : "IXSCAN", "indexName" : "b_1" } ] } }
인덱스 병합
익소르
인덱스 교차와 마찬가지로 Amazon DocumentDB에는 $or
연산자를 위한 inputStages
배열이 있는 IXOR
스테이지가 포함될 수 있습니다.
db.foo.find({"$or": [{"a": {"$gt": 2}}, {"b": {"$lt": 2}}]})
위 쿼리의 경우 설명 출력은 다음과 같을 수 있습니다.
{ "stage" : "FETCH", "inputStage" : { "stage" : "IXOR", "inputStages" : [ { "stage" : "IXSCAN", "indexName" : "a_1" }, { "stage" : "IXSCAN", "indexName" : "b_1" } ] } }
다중 인덱스 교집합/병합
Amazon DocumentDB는 여러 인덱스 교차 또는 유니온 단계를 함께 결합한 다음 결과를 가져올 수 있습니다. 예:
{ "stage" : "FETCH", "inputStage" : { "stage" : "IXOR", "inputStages" : [ { "stage" : "IXSCAN", ... }, { "stage" : "IXAND", "inputStages" : [ { "stage" : "IXSCAN", ... }, { "stage" : "IXSCAN", ... } ] } ] } }
인덱스 교차 또는 유니온 스테이지의 사용은 인덱스 유형(스파스, 복합 등)의 영향을 받지 않습니다.
복합 인덱스
Amazon DocumentDB 복합 인덱스 사용은 인덱싱된 필드의 시작 부분에만 국한되지 않습니다. 접미사 부분이 있는 인덱스를 사용할 수 있지만 그다지 효율적이지 않을 수 있습니다.
예를 들어, { a: 1, b: -1 }
의 복합 인덱스는 아래 세 가지 쿼리를 모두 지원할 수 있습니다.
db.orders.find( { a: 1 } } )
db.orders.find( { b: 1 } } )
db.orders.find( { a: 1, b: 1 } } )
정렬 단계
요청된 정렬 키에 인덱스가 있는 경우 Amazon DocumentDB는 인덱스를 사용하여 순서를 확인할 수 있습니다. 이 경우 결과에는 SORT
단계가 아닌 IXSCAN
단계가 포함됩니다. 옵티마이저가 일반 정렬을 선호하는 경우 다음과 같은 단계가 포함됩니다.
{ "stage" : "SORT", "sortPattern" : { "a" : 1, "b" : -1 } }
그룹 단계
Amazon DocumentDB는 다음과 같은 두 가지 그룹 전략을 지원합니다.
SORT_AGGREGATE
: 온 디스크 정렬 집계.HASH_AGGREGATE
: 인 메모리 해시 집계.