본문 바로가기

카테고리 없음

MySQL 성능 개선 프로젝트 7

배송이 완료될 경우 고객은 해당 배송 기사에 대해 리뷰를 작성할 수 있다.

그리고 해당 리뷰를 바탕으로 관리자가 배송 기사의 실적을 확인할 수 있는 기능이 필요하다.

고려한 선택지는 세 가지였는데,

첫 번째는 실적을 입력하는 테이블을 새로 만드는 것이다.

컬럼으로는 배송기사의 id, 평균 평점, 노동 시간, 총 건수가 있는데 이를 최신화 시켜주기 위해서는 배송 리뷰가 입력될 때마다 트리거를 이용해 반영하기, 이벤트 스케쥴러를 이용해 특정한 시간마다 갱신하기 두가지 방법이 있을것이다.

이 방법의 장점은 테이블 조회만 하면 되므로 매우 간단하고, 빠르다는 것이다. 하지만 최신화를 위해 트리거를 이용한다면 리뷰가 많이 생성될 때 성능저하가 우려되고, 이벤트 스케쥴러를 사용한다면 실시간으로 결과가 반영되지 않을것이다.

 

두 번째 방법은 필요할 때마다 그냥 SELECT쿼리문을 실행하는 것이다. 하지만 이 방법도 매번 복잡한 쿼리문을 실행해야 한다는 번거로움이 있다.

 

세 번째 방법은 view 테이블을 생성해 필요할때마다 view를 조회하는 것이다. view 테이블은 참조하는 테이블이 변화가 생기면 그에 따라 조회하는 값도 달라지므로 실시간으로 변화를 볼 수 있고, 복잡한 쿼리문도 매번 작성할 필요가 없다.

그래서 view 테이블을 이용해서 실적 조회를 구현해보았다.

 

CREATE VIEW delivery_performance_view as
SELECT
  dw.worker_id,
  dw.name,
  coalesce(AVG(dr.score), 0) AS avg_score,
  DATEDIFF(CURDATE(), dw.joined_date) AS worked_time,
  coalesce(COUNT(DO.worker_id), 0) AS delivery_num
FROM delivery_worker dw
LEFT JOIN delivery_review dr ON dw.worker_id = dr.worker_id
LEFT JOIN delivery_order DO ON dw.worker_id = DO.worker_id
GROUP BY dw.worker_id
;

 

해당 view를 조회한 결과

 

50만건을 조회하는데에 6.672초가 걸렸다.

생각한것보다 더 오래 걸린것 같아서 EXPLAIN을 통해 실행계획을 확인해 보았다.

 

배송 기사 테이블에서 임시테이블을 생성하는것과 조인 버퍼가 사용되고 있음을 확인했다.

이는 최적화된 성능이라고 보기가 어렵다.

아마 조인하는 과정에서 배송기사 id에 대해 인덱스가 설정되어 있지 않아서 그런거라 예상되었다.

 

 

그래서 인덱스를 생성해주고 다시 실행하니

 

 

3.843초로 시간이 줄어든 것을 확인할 수 있었다.

 

 

 

실행계획을 확인해보니 더 이상 임시테이블과 조인 버퍼를 사용하지 않는것을 확인할 수 있었다.