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

MongoDB count() 속도가 느릴 때 해결 방법 – ensureIndex()로 성능 개선하기

MongoDB count()가 느린 이유와 해결 방법

MongoDB에서 count() 메서드의 실행 속도가 느린 가장 큰 원인은, 검색 조건에 해당하는 필드에 인덱스가 없어 컬렉션 전체를 처음부터 끝까지 스캔(collection scan)하기 때문입니다. 이 문제는 ensureIndex()를 사용해 조건 필드에 인덱스를 미리 생성해 두면 크게 개선할 수 있습니다.

실제 동작을 이해하기 위해 예제용 컬렉션을 만들고 문서를 삽입해 보겠습니다.

1. 테스트 컬렉션 생성 및 문서 삽입

> db.countPerformanceDemo.insertOne({"StudentName":"John","StudentCountryName":"US"});
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5c8ebcf82f684a30fbdfd55f")
}
> db.countPerformanceDemo.insertOne({"StudentName":"Mike","StudentCountryName":"UK"});
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5c8ebd042f684a30fbdfd560")
}
> db.countPerformanceDemo.insertOne({"StudentName":"David","StudentCountryName":"AUS"});
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5c8ebd112f684a30fbdfd561")
}
> db.countPerformanceDemo.insertOne({"StudentName":"Carol","StudentCountryName":"US"});
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5c8ebd1a2f684a30fbdfd562")
}
> db.countPerformanceDemo.insertOne({"StudentName":"Bob","StudentCountryName":"UK"});
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5c8ebd212f684a30fbdfd563")
}

> db.countPerformanceDemo.insertOne({"StudentName":"David","StudentCountryName":"UK"});
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5c8ebd9a2f684a30fbdfd564")
}
> db.countPerformanceDemo.insertOne({"StudentName":"David","StudentCountryName":"US"});
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5c8ebd9e2f684a30fbdfd565")
}

총 7개의 문서가 저장되었습니다. find() 메서드로 전체 문서를 확인해 보겠습니다.

2. 저장된 문서 확인

> db.countPerformanceDemo.find().pretty();

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

{
   "_id" : ObjectId("5c8ebcf82f684a30fbdfd55f"),
   "StudentName" : "John",
   "StudentCountryName" : "US"
}
{
   "_id" : ObjectId("5c8ebd042f684a30fbdfd560"),
   "StudentName" : "Mike",
   "StudentCountryName" : "UK"
}
{
   "_id" : ObjectId("5c8ebd112f684a30fbdfd561"),
   "StudentName" : "David",
   "StudentCountryName" : "AUS"
}
{
   "_id" : ObjectId("5c8ebd1a2f684a30fbdfd562"),
   "StudentName" : "Carol",
   "StudentCountryName" : "US"
}
{
   "_id" : ObjectId("5c8ebd212f684a30fbdfd563"),
   "StudentName" : "Bob",
   "StudentCountryName" : "UK"
}
{
   "_id" : ObjectId("5c8ebd9a2f684a30fbdfd564"),
   "StudentName" : "David",
   "StudentCountryName" : "UK"
}
{
   "_id" : ObjectId("5c8ebd9e2f684a30fbdfd565"),
   "StudentName" : "David",
   "StudentCountryName" : "US"
}

3. 인덱스 생성으로 count() 성능 개선

이제 count()의 성능을 높이기 위해 자주 검색하는 조건 필드인 StudentName에 인덱스를 생성합니다.

> db.countPerformanceDemo.ensureIndex({"StudentName":1});
{
   "createdCollectionAutomatically" : false,
   "numIndexesBefore" : 1,
   "numIndexesAfter" : 2,
   "ok" : 1
}

출력 결과에서 numIndexesAfter 값이 1에서 2로 증가한 것을 확인할 수 있습니다. 즉, 기본 _id 인덱스 외에 StudentName 오름차순 인덱스가 새로 추가된 것입니다.

4. 인덱스 적용 후 count() 실행

인덱스가 준비되었으므로, 이제 StudentName이 "David"인 레코드 수를 세어 보겠습니다.

> db.countPerformanceDemo.find({"StudentName":"David"}).count();

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

3

조건에 일치하는 문서가 3건 있다는 결과가 반환됩니다. 인덱스 덕분에 MongoDB는 컬렉션 전체를 스캔하지 않고 인덱스만 조회해 개수를 빠르게 계산할 수 있으므로, 데이터가 수백만 건 이상으로 많아질수록 그 성능 차이는 더욱 커집니다.

참고: 최신 버전에서는 createIndex() 사용 권장

ensureIndex()는 MongoDB 3.0부터 지원 중단(deprecated)된 메서드입니다. 실무 환경에서는 동일한 역할을 하는 createIndex()를 사용하는 것이 좋습니다.

> db.countPerformanceDemo.createIndex({"StudentName":1});

또한 MongoDB 4.0.3 이상에서는 count() 대신 집계 파이프라인의 $match$group, 또는 estimatedDocumentCount() / countDocuments()를 활용하면 더 정확하고 효율적인 카운트 처리가 가능합니다.