8초의 악몽: 쿼리 최적화를 통한 99.9% 지연 시간 감소 사례

Nabeelah Yousuph - The 8-Second Nightmare: How One Change Reduced Latency by 99.9%

작성자
Friendly rb
발행일
2025년 07월 01일

핵심 요약

  • 1 프로덕션 시스템에서 8초 이상 소요되던 지연 쿼리를 `EXPLAIN` 및 `EXPLAIN ANALYZE`를 활용하여 심층 분석했습니다.
  • 2 복합 인덱스 규칙 미준수와 불필요하게 많은 레코드 스캔이 성능 저하의 주원인임을 식별했습니다.
  • 3 employee_id를 기준으로 attendant_shift 테이블을 먼저 필터링하는 한 줄의 코드 변경으로 쿼리 지연 시간을 99.9% 단축했습니다.

도입

본 발표는 프로덕션 시스템에서 발생하는 지연 쿼리 문제를 해결한 경험을 공유합니다. 특히, 시간 추적(time tracking) 도메인의 핵심 서비스 중 하나인 `update_incident_aggregate_shift_location_service`에서 발생하는 8초 이상의 긴 지연 시간이 사용자 경험 저하와 시스템 리소스 낭비를 초래하는 '8초의 악몽'으로 다가왔습니다. 본 사례를 통해 문제 진단부터 해결까지의 과정을 상세히 설명하고, 쿼리 최적화의 중요성을 강조합니다.

문제 진단 및 원인 분석

update_incident_aggregate_shift_location_service가 8~10초의 지연을 보였습니다. EXPLAIN 분석 결과, attendant_shifts 테이블은 reference_date 필터링 시 PRIMARY KEY만 사용했습니다. EXPLAIN ANALYZE를 통해 다음 원인을 파악했습니다. * 복합 인덱스 규칙 미준수: (employee_id, reference_date) 복합 인덱스가 있었으나, 쿼리가 employee_id를 먼저 사용하지 않아 인덱스가 비활성화되었습니다. * 비효율적인 데이터 스캔: 인덱스 미활용으로 수백만 건의 전체 테이블 스캔이 발생, 단 1행 반환에 9.4초 이상 소요되는 비효율을 초래했습니다.

해결책 및 결과

attendant_shifts 테이블 쿼리 시 employee_id를 먼저 필터링한 후 reference_date를 필터링하도록 로직을 수정했습니다. 이는 Active Record 스코프에 by_employee_id 필터를 추가하는 한 줄의 코드 변경으로 구현되었습니다.

수정 후 EXPLAIN 결과, attendant_shifts(employee_id, reference_date) 복합 인덱스를 올바르게 활용했습니다. EXPLAIN ANALYZE 결과, 쿼리 실행 시간은 9.4초에서 0.003초로 99.9% 감소했으며, 처리 비용도 현저히 줄었습니다.

결론

본 사례는 데이터베이스 쿼리 최적화의 중요성과 그 효과를 명확히 보여줍니다. 특히, 인덱스의 작동 방식, 특히 복합 인덱스의 컬럼 순서 규칙을 정확히 이해하고 이를 쿼리에 반영하는 것이 얼마나 중요한지 깨달았습니다. 단순히 '문법적 설탕(syntactic sugar)'에 의존하기보다는, 쿼리가 데이터베이스 내부에서 어떻게 실행되는지(`under the hood`)를 깊이 이해하고 직접 분석하는 '손을 더럽히는(getting your hands dirty)' 작업이 성능 비효율성을 해소하는 데 필수적입니다. 이처럼 작은 코드 변경 하나가 시스템의 전체적인 지연 시간을 획기적으로 줄이고 사용자 경험을 개선할 수 있음을 입증했습니다.

댓글 0

댓글 작성

0/1000
정중하고 건설적인 댓글을 작성해 주세요.

아직 댓글이 없습니다

첫 번째 댓글을 작성해보세요!