Computer >> 컴퓨터 >  >> 프로그래밍 >> MongoDB

MongoDB에서 hint()를 사용해 인덱스 대신 BasicCursor(컬렉션 스캔)를 강제하는 방법

MongoDB에서 특정 쿼리가 인덱스를 사용하지 않도록 강제하고 싶다면 hint() 메서드를 활용하면 됩니다. hint()에 { $natural: 1 } 옵션을 지정하면 MongoDB는 기존 인덱스를 모두 무시하고 컬렉션을 자연스러운(natural) 순서, 즉 디스크에 저장된 순서대로 처음부터 끝까지 스캔하는 BasicCursor(컬렉션 스캔) 방식으로 쿼리를 실행합니다.

이 기법은 인덱스 사용 여부에 따른 성능 차이를 비교하거나, 쿼리 플래너의 동작을 디버깅할 때 유용하게 활용됩니다.

1. 테스트 컬렉션 생성 및 데이터 삽입

먼저 demo31 컬렉션의 StudentFirstName 필드에 인덱스를 생성하고, 샘플 문서들을 삽입해 보겠습니다.

> db.demo31.createIndex({"StudentFirstName":1});
{
    "createdCollectionAutomatically" : true,
    "numIndexesBefore" : 1,
    "numIndexesAfter" : 2,
    "ok" : 1
}
> db.demo31.insertOne({"StudentFirstName":"John"});
{ "acknowledged" : true, "insertedId" : ObjectId("5e174f8fcfb11e5c34d898c1") }
> db.demo31.insertOne({"StudentFirstName":"Jace"});
{ "acknowledged" : true, "insertedId" : ObjectId("5e174f97cfb11e5c34d898c2") }
> db.demo31.insertOne({"StudentFirstName":"Chris"});
{ "acknowledged" : true, "insertedId" : ObjectId("5e174f9ccfb11e5c34d898c3") }
> db.demo31.insertOne({"StudentFirstName":"James"});
{ "acknowledged" : true, "insertedId" : ObjectId("5e174fa0cfb11e5c34d898c4") }

2. find()로 전체 문서 확인하기

find() 메서드를 사용하면 컬렉션에 저장된 모든 문서를 조회할 수 있습니다.

> db.demo31.find();

위 쿼리는 다음과 같은 결과를 출력합니다.

{ "_id" : ObjectId("5e174f8fcfb11e5c34d898c1"), "StudentFirstName" : "John" }
{ "_id" : ObjectId("5e174f97cfb11e5c34d898c2"), "StudentFirstName" : "Jace" }
{ "_id" : ObjectId("5e174f9ccfb11e5c34d898c3"), "StudentFirstName" : "Chris" }
{ "_id" : ObjectId("5e174fa0cfb11e5c34d898c4"), "StudentFirstName" : "James" }

3. hint({ $natural: 1 })로 BasicCursor 강제하기

다음은 정규식 조건이 포함된 쿼리에서 hint()를 사용해 인덱스 대신 BasicCursor를 사용하도록 강제하는 예제입니다.

> db.demo31.find({"StudentFirstName": {$regex: '^Ja'}}).hint({ $natural: 1});

실행 결과는 다음과 같습니다.

{ "_id" : ObjectId("5e174f97cfb11e5c34d898c2"), "StudentFirstName" : "Jace" }
{ "_id" : ObjectId("5e174fa0cfb11e5c34d898c4"), "StudentFirstName" : "James" }

동작 원리 정리

$regex: '^Ja' 조건은 "Ja"로 시작하는 이름(Jace, James)을 찾습니다. 일반적으로라면 MongoDB는 접두사 검색에 최적화된 StudentFirstName 인덱스를 선택하지만, .hint({ $natural: 1 })을 추가했기 때문에 쿼리 플래너가 인덱스를 완전히 무시하고 컬렉션 전체를 순차적으로 스캔합니다.

결과적으로 explain() 실행 계획에서 COLLSCAN(BasicCursor) 단계가 표시되는 것을 확인할 수 있으며, 이를 통해 인덱스 사용 여부에 따른 성능 차이를 직접 비교해 볼 수 있습니다.