본문 바로가기

개발일지/TIL

[231102] MySQL 데이터 분석을 위한 SQL 작성... 더 나아지기

데이터 건수가 많아

💬 건수가 2억 건 이상이 되니 데이터를 원하는 형태로 추출하는 것이 너무 느렸습니다. 30분 이상.. 1시간 이상 돌려도 원하는 동작이 완료되지 않았습니다. 그래서 저번에 6년 차 개발자님이 조언해 주신 대로 적용을 해보기로 했다. 

 

✔ Explain

💬 먼저 각 쿼리에 대한 실행 전략을 확인하기 위해 Explain을 사용을 해보았다. 내가 작성한 쿼리는 2억 건을 그대로 가져다가 쓰는 형식으로 실행이 된다는 것을 확인할 수 있었다. 문제를 확인했으니 이것을 개선하기 위한 방법을 고려해 보았다.

 

✔ Where로 데이터의 건수 줄이기

💬 전체 기간으로 잡았던 것을 1년 기간으로 줄여보았다. 줄여보니 확실히 Explain에서 보여주는 Row 건수는 줄어드는 것을 확인할 수 있었다. 하지만 아직 수준 미달이라 1달 단위로 줄여보았지만 내가 원하는 만큼의 성능을 보여주지 않았다. 

 

✔ Index

💬 인덱스를 거는 방법을 추가적으로 적용해 보려고 시도했다. Group By를 통해서 데이터를 그룹화해서 가져오다 보니 인덱스가 Group By에 영향을 미쳤습니다. 하지만 기존 테이블에 적용되어 있던 인덱스에는 제가 Group By로 사용했던 칼럼들이 없었습니다. 이를 해결하기 위해 별도의 통계 테이블을 만들고 데이터를 이전한 후 내가 내고자 하는 Group By 칼럼들을 기준으로 인덱스를 걸어주었습니다.

 

✔ IN 대신 Exists 사용하기

💬 추가적으로 테이블 간의 값 비교를 위해 서브쿼리와 함께 IN을 사용했다. 하지만 IN은 중간에 원하는 값을 찾더라도 끝까지 검색을 한다고 한다. 그러기 때문에 속도가 많이 느리다고 한다. 중간에 값을 찾으면 멈추는 Exists를 사용하는 것이 IN에 비해 속도가 빠르다. IN으로 되어있는 것을 Exists으로 변경을 했다. 이후에는 JOIN을 더 공부를 해서 적용을 해보면 좋을 것 같다.

 

✔ 문제점

💢 인덱스를 걸었음에도 느리다는 것을 확인했다. Explain을 통해 확인해 보니 index를 사용하지 않는 것을 보였다. 그 이유를 찾아보니 인덱스를 건 순서와 Group by의 순서가 동일해야 한다는 것을 알았다. 그리고 숫자도 같거나 그 이하의 칼럼 명을 사용해야 한다는 것도 알았다.

✅ 인덱스와 동일하게 Group by의 순서를 지켜줬다. 이것을 적용하고 Explain을 사용해 보니 내가 적용한 인덱스가 사용되는 것을 확인할 수 있었다.

 

✔ 결과

✅ 위에 것들을 적용하니 실제 1시간 이상 지나도 끝나지 않던 작업이 전체 데이터를 추출하는데 20분도 걸리지 않았다. 이번을 통해 SQL를 많이 학습할 수 있었다. 하지만 이후에는 테이블을 복사할 수 없는 상황에서도 여전히 성능적으로 개선하기 위해서는 현재 내가 부족한 SQL를 더 많이 공부하고 실습해 볼 필요가 있는 것 같다.