미리캔버스, DocumentDB 인덱스 최적화로 쿼리 성능 50% 개선!
미리캔버스가 MongoDB Atlas에서 Amazon DocumentDB로 전환 후 쿼리 성능 저하 문제를 겪었으며, 인덱스 최적화(Index Optimization)를 통해 해결
Partial Index, $or + sort, Regex, Hot Document 등 4가지 주요 문제점을 분석하고, 각 문제에 대한 구체적인 해결 방안 제시
프로덕션 환경에서의 쿼리 튜닝, 인덱스 통계 워밍, MVCC GC, 압축률 차이 등 운영 노하우(Operational Know-how) 공유
Amazon DocumentDB의 Query Planner와 MongoDB의 차이점을 인지하고, explain() 활용을 통해 인덱스 활용 여부 검증의 중요성 강조
인덱스 최적화를 통해 쿼리 성능을 개선하고, 안정적인 서비스 운영(Stable Service Operation)을 위한 실질적인 가이드 제공
Amazon DocumentDB와 MongoDB의 쿼리 플래너(Query Planner) 차이점
본문에 따르면 Amazon DocumentDB의 쿼리 플래너는 MongoDB와 동작 방식에 차이가 있어, 기존 MongoDB 환경에서 사용하던 인덱스가 DocumentDB에서는 예상과 다르게 동작하는 경우가 발생한다. 특히, partial index 활용 조건(Partial Index Usage Condition)이 MongoDB보다 엄격하여, 쿼리 필터와 partialFilterExpression이 정확히 일치해야 인덱스를 사용한다. 이러한 차이로 인해, MongoDB에서 문제없이 동작하던 쿼리가 DocumentDB에서는 성능 저하를 유발할 수 있으며, explain()을 통해 인덱스 활용 여부를 반드시 확인해야 한다. 미리캔버스는 이러한 차이점을 인지하고, explain() 활용을 통해 쿼리 성능을 지속적으로 개선했다.
Partial Index 활용 시 주의사항
미리캔버스 사례에서 Amazon DocumentDB의 partial index는 MongoDB와 달리 쿼리 조건과 partialFilterExpression이 정확히 일치해야 활용된다는 점을 강조한다. 예를 들어, partialFilterExpression이 `{ itemIdx: { $exists: true } }`인데 쿼리 조건이 `{ itemIdx: { $in: [...] } }`인 경우, 인덱스가 사용되지 않는다. 해결책으로, 쿼리 패턴에 맞게 partialFilterExpression을 재설계하거나, 일반 복합 인덱스를 사용하는 방법을 제시한다. partial index의 엄격한 조건(Strict Condition)을 이해하고, explain()을 통해 인덱스 활용 여부를 확인하는 것이 중요하다.
$or + sort 패턴의 문제점과 해결 방안
글에서는 Amazon DocumentDB가 MongoDB와 달리 SORT_MERGE를 지원하지 않아, $or + sort 쿼리 시 전체 결과를 메모리에서 정렬해야 하는 문제를 지적한다. 이는 대량의 fetch와 높은 지연을 유발하며, 쿼리 성능 저하의 주요 원인이 된다. 해결책으로, 쿼리를 분리하여 애플리케이션 레벨에서 병합하거나, 복합 인덱스를 재설계하여 $or 조건을 제거하는 방법을 제시한다. SORT_MERGE 부재(Absence of SORT_MERGE)를 고려하여 인덱스를 설계하고, 애플리케이션 레벨에서의 병합을 통해 성능을 개선하는 것이 핵심이다.
Regex 쿼리 최적화: Prefix Match 활용
미리캔버스는 파일 경로 기반 쿼리에서 정규표현식(Regex)을 사용하다가, Amazon DocumentDB에서 prefix match만 인덱스를 활용할 수 있다는 제약에 직면했다. 해결책으로, regex 대신 range 쿼리로 변환하여 확실하게 IXSCAN을 활용하는 방법을 제시한다. 예를 들어, `path: RegExp("^MY_DRIVE:/example-folder-id/")` 쿼리를 `$gt`와 `$lt`를 사용한 range 쿼리로 변환하여 인덱스 힌트 없이 IXSCAN을 활용했다. Regex를 Range 쿼리로 변환(Regex to Range Conversion)을 통해 쿼리 성능을 향상시킨 사례이다.
Hot Document 문제와 해결: ElastiCache 활용
미리캔버스는 드라이브 서비스에서 $inc 연산이 특정 document에 집중되어 document-level lock 경합이 발생하는 'hot document' 문제를 겪었다. Amazon DocumentDB의 Performance Insights를 통해 document-level lock 대기 시간을 확인하고, 문제점을 진단했다. 해결책으로, 카운터를 Amazon ElastiCache(Redis)로 분리하여 빈번한 $inc 연산을 처리하고, 주기적으로 배치 업데이트를 통해 Amazon DocumentDB에 반영했다. Redis를 활용한 카운터 분리(Counter Separation)를 통해 document-level lock 경합을 해소하고, 쓰기 지연을 개선했다.
프로덕션 쿼리 튜닝 및 운영 노하우
미리캔버스는 인덱스 설계 외에도, 프로덕션 환경에서 쿼리 형태를 변경하여 성능을 개선했다. 정렬 관련 인덱스 스캔 범위를 축소하고, 불필요한 정렬 조건 및 샤드키 조건을 제거하여 쿼리 플래너가 최적의 인덱스를 선택하도록 유도했다. 또한, 쿼리 프로파일러(Query Profiler)를 활용하여 slow query를 추적하고, 인덱스 통계 워밍(Index Statistics Warming)을 통해 쿼리 플래너가 최적의 인덱스를 선택하도록 했다. 프로덕션 쿼리 튜닝(Production Query Tuning)과 인덱스 통계 워밍(Index Statistics Warming)을 통해 쿼리 성능을 지속적으로 관리하고 개선하는 것이 중요하다.