본문 바로가기
프로젝트 이슈

RunGuard 개발 EXPLAIN

by BIGENGINEER 2026. 7. 8.

 

EXPLAIN

- MySQL이 쿼리를 실행할 때 어떤 인덱스를 썼는지, 얼마나 효율적으로 조회했는지 보여주는 분석 도구

 

key : 실제 사용한 인덱스 이름

type : 조회 방식, ref면 꽤 괜찮은 편

rows : mysql이 예상한 조회 행 수

extra : 추가 실행 정보

 

 

!!! Using filesort !!!

- 인덱스 순서대로 바로 결과를 못 뽑아서 MySQL이 따로 정렬했다는 뜻

 

즉, 조건 검색은 인덱스로 했지만, order by 순서와 인덱스 순서가 안 맞음

-> mysql이 결과를 다시 정렬함

= Using filesort

 

 

SELECT *
FROM workout_segments
WHERE workout_id = 1
  AND is_anomaly = 1
ORDER BY segment_index ASC;

1. workout_id가 1인 구간 찾기

2. 그중 이상 구간만 찾기

3. segment_index 순서대로 정렬하기

 

기존 인덱스: (workout_id, is_anomaly, anomaly_score)

 

근데, segment_index 순서대로 정렬하길 원함 -> 기존 인덱스에서 anomaly_score는 필요 없음

 

즉, workout_id, is_anomaly 조건으로 데이터 찾았는데, 정렬은 segment_index로 되지 않음

그래서 MySQL이 따로 정렬한 것 = Using filesort 발생

 

 

 

<새로 제안한 인덱스> 

CREATE INDEX idx_workout_segments_workout_anomaly_segment_index
ON workout_segments (workout_id, is_anomaly, segment_index);

 

- 근데 새로 제안한 인덱스는 구간 순서대로 보기 좋은 인덱스임. 

- 만약 이상 점수 순으로 보기 좋은 인덱스를 원한다면 기존을 유지하는게 맞음

 


SELECT *
FROM workouts
WHERE user_id = 1
  AND started_at BETWEEN '2026-07-02 00:00:00' AND '2026-07-08 23:59:59'
ORDER BY started_at DESC;

1. user_id가 1인 운동 찾기
2. started_at이 이번 주 범위 안인 것 찾기
3. started_at 최신순으로 정렬하기

 

 

근데 실제로 MySQL이 고른 인덱스는 (user_id, sport_type, started_at)

- 쿼리에 sport_type이 없음 즉, 엔티티에는 있지만 쿼리에는 없음 

 

 

아, 테이블 만들 때 인덱스 생성함 -> 인덱스를 잘 생성하는게 중요함

근데, 고르는건 MySQL 옵티마이저의 선택이라 이후 수정이 필요한 것

 

 

 

 

!! Using filesort는 조건 검색 후 MySQL이 결과를 따로 정렬했다는 뜻이다.
즉, 인덱스를 사용하긴 했지만 ORDER BY까지 인덱스로 해결하지는 못한 상태다.
그래서 WHERE 조건 컬럼 뒤에 ORDER BY 컬럼이 이어지는 복합 인덱스를 추가하면 정렬 비용을 줄일 수 있다.

 

 


 

그럼 어떻게 수정?

 

1. FORCE INDEX로 수정할 수 있는데 

EXPLAIN
SELECT *
FROM workouts FORCE INDEX (idx_workouts_user_started_at)
WHERE user_id = 1
  AND started_at BETWEEN '2026-07-02 00:00:00' AND '2026-07-08 23:59:59'
ORDER BY started_at DESC;

 

-> MYSQL아 네가 알아서 인덱스 고르지 말고 강제로 (user_id, started_at) 인덱스 써봐라

 

 

 

2. ANALYZE TABLE 사용

 - MySQL 한테 테이블 통계 정보 다시 계산해줘, 그래야 다음에 인덱스 잘 고를 수 있어 

 

=>  MySQL은 쿼리 실행 전에 어떤 인덱스 쓸지 판단, 이때 테이블 통계 정보 참고

=> 오래되건 데이터 많이 바뀌면 이상한 인덱스 고름 그래서 ANALYZE TABLE 사용으로 통계 갱신

 

 

 

 

<개선 결과>

CREATE INDEX idx_workout_segments_workout_anomaly_segment_index
ON workout_segments (workout_id, is_anomaly, segment_index);

ANALYZE TABLE workout_segments;
ANALYZE TABLE workouts;
ANALYZE TABLE condition_events;

EXPLAIN
SELECT *
FROM workout_segments
WHERE workout_id = 1
  AND is_anomaly = 1
ORDER BY segment_index ASC;

 

- 새 인덱스 생성 -> 통계 갱신 -> 확인

1 SIMPLE workout_segments   ref uk_workout_segments_workout_index,idx_workout_segments_anomaly,idx_workout_segments_workout_anomaly_segment_index idx_workout_segments_workout_anomaly_segment_index 9 const,const 1 100.00  

-> Extra = NULL 값 !!

 

 

 

EXPLAIN
SELECT *
FROM workouts FORCE INDEX (idx_workouts_user_started_at)
WHERE user_id = 1
  AND started_at BETWEEN '2026-07-02 00:00:00' AND '2026-07-08 23:59:59'
ORDER BY started_at DESC;

 

1 SIMPLE workouts   range idx_workouts_user_started_at idx_workouts_user_started_at 13   1 100.00 Using index condition; Backward index scan

-> Using file 없어짐!