쿼리 최적화는 쿼리 작업에서 프로세스 해야 하는 데이터의 양을 줄여 읽기 작업의 효율성 높입니다. 인덱스, 프로젝션, 쿼리 제한을 사용하여 쿼리 성능을 향상하고 리소스 소비를 줄입니다.
쿼리를 지원하는 인덱스 만들기
일반적으로 실행되는 쿼리에 대해 인덱스를 생성합니다. 쿼리 여러 필드를 검색하는 경우 복합 인덱스 만듭니다. 인덱스 사용하면 인덱스 쿼리 컬렉션 의 모든 문서 스캔해야 하므로 성능이 향상됩니다.
예시 들어 inventory
컬렉션 의 type
필드 에 대한 다음 쿼리 가정해 보겠습니다.
let typeValue = <someUserInput>; db.inventory.find( { type: typeValue } );
이 쿼리 의 성능을 inventory
개선하려면 type
필드 의 컬렉션 에 인덱스 추가합니다.1[] 에서 mongosh
메서드를 사용하여 인덱스를 db.collection.createIndex()
생성합니다.
db.inventory.createIndex( { type: 1 } )
쿼리 성능을 분석 하려면 설명 설명 계획 결과 해석을 참조하세요.
[1] | 단일 필드 인덱스의 경우 인덱스 의 순서는 중요하지 않습니다. 복합 인덱스의 경우 필드 순서는 인덱스 지원하는 쿼리에 영향을 줍니다. 자세한 내용은 복합 인덱스 정렬 순서를 참조하세요. |
선택적 쿼리 만들기
쿼리 선택도는 쿼리 조건자가 컬렉션 의 문서를 얼마나 잘 필터링하는지를 나타냅니다. 쿼리 선택도는 쿼리가 인덱스를 효과적으로 사용할 수 있는지 여부를 결정합니다.
선택적 쿼리가 많을수록 더 적은 비율의 문서가 일치합니다. 예를 들어 고유한 _id
필드의 동등성 매치는 최대 하나의 문서와 일치할 수 있으므로 매우 선별적입니다.
덜 선택적인 쿼리는 더 많은 비율의 문서와 일치하므로 인덱스를 효과적으로 사용할 수 없습니다.
예를 들어, 부등호 연산자 $nin
과 $ne
는 대부분의 인덱스와 일치하기 때문에 매우 선택적이지 않습니다. 결과적으로, 인덱스가 있는 $nin
또는 $ne
컬렉션의 모든 문서를 스캔해야 하는 $nin
또는 $ne
쿼리보다 빈번하게 성능이 떨어질 수 있습니다.
regular expressions
의 선택성은 표현식 자체에 따라 다릅니다. 자세한 내용은 표현식 및 인덱스 사용을 참조하세요.
필요한 데이터만 프로젝트
문서에서 필드의 하위 집합이 필요한 경우 필요한 필드만 반환하여 성능을 개선할 수 있습니다. 프로젝션은 네트워크 트래픽과 처리 시간을 줄입니다.
예시 들어 posts
컬렉션 에 대한 쿼리 timestamp
, title
, author
및 abstract
필드만 필요한 경우 프로젝션 에서 해당 필드를 지정합니다.
db.posts.find( {}, { timestamp : 1, title : 1, author : 1, abstract : 1} ).sort( { timestamp : -1 } )
집계 단계를 사용하는 경우, 이 단계는 일반적으로 파이프라인 의 마지막 단계로, 클라이언트 에 반환할 필드를 지정하는 데 사용됩니다.$project
파이프라인 의 시작 또는 중간에 $project
단계를 사용하여 후속 파이프라인 단계로 전달되는 필드 수를 줄이면 데이터베이스 이 최적화를 자동으로 수행하므로 성능이 향상되지 않을 수 있습니다.
프로젝션 사용에 대한 자세한 내용은 쿼리에서 반환할 프로젝트 필드를 참조하세요.
쿼리 결과 제한
MongoDB 커서는 결과를 배치로 반환합니다. 원하는 결과 수를 알고 있는 경우 메서드에 limit()
해당 값을 지정합니다. 결과를 제한하면 네트워크 리소스에 대한 수요가 줄어듭니다.
일반적으로 결과 제한은 어떤 문서가 반환되는지 알 수 있도록 결과를 정렬할 때 가장 유용합니다. 예시 들어 posts
컬렉션 에 대한 쿼리 의 10 결과만 필요한 경우 다음 쿼리 실행 .
db.posts.find().sort( { timestamp : -1 } ).limit(10)
결과 제한에 대한 자세한 내용은 를 limit()
참조하세요.
인덱스 힌트 사용
쿼리 옵티마이저 저는 일반적으로 특정 작업에 가장 적합한 인덱스 선택합니다. 그러나 메서드를 사용하여 MongoDB 특정 인덱스 사용하도록 강제할 수 hint()
있습니다. 성능 테스트를 hint()
지원 여러 인덱스에 나타나는 필드 쿼리하여 MongoDB 올바른 인덱스 사용하도록 보장하려면 를 사용하세요.
서버 측 작업 사용
MongoDB의 연산자 사용하여 문서의 값을 증가 또는 감소시킵니다. 연산자 문서 선택하고 클라이언트 에서 간단한 수정을 수행한 다음 전체 문서 서버 에 쓰는 대신 서버 측에서 필드 값을 증가시킵니다.$inc
연산자 $inc
또한 두 개의 애플리케이션 인스턴스가 문서 를 쿼리 , 필드 수동으로 증가시키고, 동시에 전체 문서 다시 저장할 때 발생하는 경합 상태를 방지하는 데 도움이 될 수 있습니다.
해당 쿼리 실행
커버드 쿼리(covered query)는 인덱스만을 사용하여 완전히 충족할 수 있는 쿼리로, 문서를 검사할 필요가 없습니다. 인덱스가 쿼리를 커버 할 때는 다음 조건이 모두 적용됩니다:
쿼리의 모든 필드(애플리케이션에서 지정한 필드와 샤딩 목적 등 내부적으로 필요한 필드 모두)는 인덱스의 일부입니다.
결과에서 반환되는 모든 필드가 동일한 인덱스에 있습니다.
쿼리에서
null
과 같은 필드가 없는 경우. 예를 들어 다음 쿼리 조건자는 지원되는 쿼리를 반환할 수 없습니다.{ "field": null }
{ "field": { $eq: null } }
예시
inventory
컬렉션에는 type
및 item
필드에 대한 다음 인덱스가 있습니다.
db.inventory.createIndex( { type: 1, item: 1 } )
이 인덱스는 type
및 item
필드를 쿼리하고 item
필드만 반환하는 다음 작업을 다룹니다.
db.inventory.find( { type: "food", item:/^c/ }, { item: 1, _id: 0 } )
지정한 인덱스가 쿼리를 포함하도록 하려면 인덱스에는 _id
필드가 포함되어 있지 않으므로 프로젝션 문서에서 명시적으로 _id: 0
를 지정하여 결과에서 _id
필드를 제외해야 합니다.
내장된 문서
인덱스는 내장된 문서 내의 필드에 대한 쿼리를 커버할 수 있습니다.
예를 들어 다음과 같은 형식의 문서가 있는 collection userdata
가 있다고 가정해 봅시다.
db.userdata.insertOne( { _id: 1, user: { login: "tester" } } )
컬렉션의 인덱스는 다음과 같습니다.
db.userdata.createIndex( { "user.login": 1 } )
{ "user.login": 1 }
인덱스는 다음 쿼리를 포함합니다.
db.userdata.find( { "user.login": "tester" }, { "user.login": 1, _id: 0 } )
참고
내장된 문서의 필드를 인덱싱하려면 점 표기법을 사용합니다. 포함된 Field에 인덱스 만들기를 참조하세요.
멀티키 커버링
인덱스가 인덱스를 멀티키로 만드는 필드를 추적하는 경우 멀티키 인덱스는 비배열 필드에 대한 쿼리를 처리할 수 있습니다.
멀티키 인덱스는 배열 필드에 대한 쿼리를 처리할 수 없습니다.
멀티키 인덱스가 포함된 지원되는 쿼리의 예는 멀티키 인덱스 페이지의 지원되는 쿼리를 참조하세요.
성능
인덱스에는 쿼리에 필요한 모든 필드가 포함되어 있기 때문에 MongoDB는 쿼리 조건을 충족하고 인덱스만을 사용하여 결과를 반환할 수도 있습니다.
인덱스만 쿼리하는 것이 인덱스 외부의 문서를 쿼리하는 것보다 훨씬 빠를 수 있습니다. 인덱스 키는 일반적으로 카탈로그에 포함된 문서보다 작으며, 인덱스는 일반적으로 RAM에서 사용 가능하거나 디스크에 순차적으로 배치됩니다.
제한 사항
인덱스 유형
모든 인덱스 유형이 쿼리를 지원할 수 있는 것은 아닙니다. 지원되는 인덱스 지원에 대한 자세한 내용은 해당 인덱스 유형의 문서 페이지를 참조하십시오.
샤드 컬렉션
mongos
에서 실행할 때, 샤드 키가 포함된 인덱스가 있는 경우에만 인덱스는 샤드된 컬렉션에 대한 쿼리를 처리할 수 있습니다.
결과 설명
쿼리가 지원되는 쿼리인지 확인하려면 db.collection.explain()
또는 explain()
메서드를 사용합니다. 지원되는 쿼리를 참조하세요.