[MongoDB] Optimizer Process

So yeong Choe·2022년 1월 31일
1

MongoDB

목록 보기
2/2
post-thumbnail

MongoDB Optimizer 프로세스는 타 DBMS의 Optimizer와 다소 상이하고, 관련 포스트가 거의 없어서 프로세스를 파악하기 어렵다.

인터넷에 정리된 문서들과 MongoDB 소스코드를 참고하여 MongoDB의 Optimizer 프로세스를 이해해보자.

해당 포스트는 MongoDB Community Server 4.2를 기준으로 작성했으며, 버전에 따라 프로세스가 상이할수 있다.

📌 1. Introduction

MongoDB는 RDBMS와 비교했을 때 데이터베이스에 대한 통계정보가 거의 없는 수준이다.
따라서 RDBMS처럼 통계정보를 이용하여 쿼리 최적화를 수행할 수가 없고, 쿼리 형태와 사용 인덱스만 비교하며 Plan을 생성하는 다소 무식한 방법을 사용한다.

이로 인한 부정확성을 보완하기 위해 MongoDB는 특수한 Evaluating 과정을 수행하여 각 후보 플랜(Candidate Plan)에 점수를 부여한다.
가장 점수가 높은 Plan은 Winning Plan으로 선정되어 Plan Cache에 저장되고, 쿼리에 사용된다.
이후에 동일한 쿼리 형태가 들어오면 Plan Cache에 있는 플랜을 사용하여 쿼리 최적화 시간을 최소화하도록 동작한다.

📌 2. Process

일단 쿼리가 들어오면, MongoDB Optimizer는 Plan Cache에 매칭되는 Plan이 있는지 검색을 수행한다.
들어온 쿼리와 동일한 쿼리 형태에 대한 Plan을 Matching Plan으로 인식한다.

A. Plan Cache에 Matching Plan이 있는 경우

  1. Evaluate Plan Performance : 캐싱된 Plan의 효율성 검증
    2-1. 캐싱된 Plan이 효율적인 경우 : 캐싱된 Plan으로 현재 쿼리를 수행한다.
    2-2. 캐싱된 Plan이 비효율적인 경우: 캐싱된 Plan을 Evict 하고, 아래의 B. Plan Cache에 매칭 플랜이 없는 경우 프로세스를 수행한다.

B. Plan Cache에 Matching Plan이 없는 경우

  1. Plan : 쿼리 형태에 맞는 Plan들을 생성하여 후보 플랜(Candidate Plan)으로 지정
  2. Work Candidate Plans : 모든 Candidate Plan에 대해 쿼리 부분 실행
  3. Pick Best Plan : 각 Candidate Plan의 점수를 책정한 후 가장 높은 점수의 플랜을 Winning Plan으로 선정
  4. Plan Cache에 Winning Plan 저장
  5. Winning Plan으로 쿼리 수행

이 중 굵게 표시된 메인 프로세스들을 좀 더 자세히 살펴보자.


2-1. Plan

타 DBMS와 달리, MongoDB는 쿼리 Plan을 생성할 때 데이터베이스의 통계 정보를 전혀 사용하지 않는다.
오직 요청된 쿼리의 형태와 인덱스 목록만 보고 Plan을 생성한다.

MongoDB는 컬렉션의 인덱스 목록 중, 요청된 쿼리와 '연관된' 인덱스를 추출하여 Indexed Plan을 생성한다.
쿼리와 인덱스의 '연관성'을 판단하는 기준은 아래와 같다.

  • 쿼리와 인덱스에 일치하는 필드가 있는가?
  • 인덱스 프리픽스가 쿼리 필드에 포함되는가?
  • hint가 사용되었는가?
  • GEO_NEAR, TEXT 인덱스인가?
  • min( ), max( )가 사용되었는가?

적절한 Indexed Plan이 없는 경우에는 COLLSCAN Plan을 생성한다.

다시 말해서, Indexed Plan이 하나라도 있으면 COLLSCAN이 더 효율적인 경우에도 COLLSCAN Plan은 생성되지 않는다는 의미이다.

🔗 2-1. Plan - Source Code(QueryPlanner::plan)


2-2. Work Candidate Plans

MongoDB는 옵티마이징에 다양한 데이터베이스 정보를 이용하지 못한다는 약점을 보완하기 위해, 모든 후보 플랜(Candidate Plan)을 동시에 조금씩 수행해보는 과정을 거친다.

반복문을 사용해 모든 Candidate Plan에 Work를 1회씩 호출하는데, 이 과정을 Working이라고 지칭하겠다.

Working은 아래 조건 중 하나를 만족할 때까지 반복적으로 수행된다.

  • Candidate Plan 중 하나라도 먼저 numResults* 만큼의 도큐먼트 반환
  • Candidate Plan 중 하나라도 먼저 쿼리 수행 완료
  • numWorks* 회 만큼 Working 수행
  • Working 중 에러가 발생한 경우
    • numWorks : (컬렉션의 데이터 개수 x 0.29) 와 10,000 중 큰 값
    • numResults : limit() 파라미터와 101 중 작은 값

🔗 2.2 Work Candidate Plans - Source Code(MultiPlanStage::pickBestPlan)
🔗 2.2 Work Candidate Plans - Source Code(MultiPlanStage::workAllPlans)


2-3. Pick Best Plan

Working이 완료된 플랜들은 아래 지표의 합으로 점수가 책정된다.

  • baseScore = 1
  • productivity = advanced / workUnits (실제 반환 도큐먼트 수 / work 횟수)
  • tieBreakers : 비효율적인 특정 작업들을 수행하지 않는 플랜에게 부여하는 보너스 점수
  • EOF Bonus : Plan Working 중 먼저 쿼리 수행을 완료한 플랜에게 부여하는 보너스 점수 (+1)

baseScore를 포함하는 이유는 아무 Plan도 선택되지 않는 No Plan Selected가 0점의 score를 가지기 때문이다.
쿼리를 수행할 때 최대한 Plan을 사용하게 하기 위해 optimizer는 기본적으로 모든 Plan에 1점의 점수를 부여한다.

tieBreakers는 쿼리 플랜이 다음의 경우를 만족할 경우 각각 epsilon* 만큼 부여하는 보너스 점수를 의미한다.

  • Fetch 스테이지가 없을 경우
  • Sort 스테이지가 없을 경우
  • Index Intersection을 사용하지 않을 경우
    • epsilon : ( 1 / ( 10 x workUnits ) ) 와 10-4 중 작은 값

EOF Bonus는 Winning Plan 선정 시에만 사용되고, Cache에 저장될 때는 점수에 포함되지 않는다.
캐싱된 Plan을 검증하는 과정에서 EOF Bonus를 얻지 못하면 실제 Plan의 효율과 관계 없이 evict될 확률이 높아지기 때문이다.

🔗 2-3. Pick Best Plan - Source Code(PlanRanker::scoreTree)

2-4. Evict Plan Cache Entry

한번 생성된 쿼리 Plan은 Plan Cache에 저장되어 있다가, 아래의 경우에 Evict된다.

  • 인덱스 Rebuild
  • 인덱스 추가 및 삭제
  • mongod 프로세스 재시작
  • 쿼리 플랜이 비효율적이라고 판단될 경우


Optimizer가 쿼리 Plan의 효율성을 검증하는 방법은 아래와 같다.

  • 캐싱된 Plan을 maxWorksBeforeReplan* 회 만큼 working
  • Working이 끝나기 전에 아래 조건 중 하나를 만족하면 캐싱된 Plan이 evict되지 않고 계속 사용됨
    • 캐싱된 Plan이 numResults* 만큼의 도큐먼트 반환
    • 캐싱된 Plan이 쿼리 수행 완료
  • 그 외의 경우 캐싱된 Plan을 evict하고 Replanning을 수행한다.
    • maxWorksBeforeReplan : 10 x decisionWorks*
    • numResults : limit() 파라미터와 101 중 작은 값
    • decisionWorks : the number of work cycle taken to decide on a winning plan when the plan was first cached

🔗 2-4. Evict Plan Cache Entry - Source Code(CachedPlanStage::pickBestPlan)

📌 3.참고자료

MongoDB 4.2 Source Code

https://www.slideshare.net/MyDBOPS/introduction-to-mongodb-execution-plan-and-optimizer?qid=116fadbd-5fa3-4cc3-9f9a-caa1dec0ebf9&v=&b=&from_search=1

https://mongoing.com/archives/5624

profile
IT 공부하는 블로그

0개의 댓글