서비스 출시 하는 데에 급급해서 솔직히 "쿼리 퀄리티" 는 안 따진지 오래다.
그렇다고 개판으로 짜진 않지만, 경력을 쌓으며 자연스레 알게 되는 기초적인 쿼리 개념들만 적용하면서 개발을 해왔다.
기초적인 것이라 함은
- 검색 쿼리를 날릴 때 해당 컬럼에 index 걸면 좋다던가..
- like %검색어% 는 풀스캔을 타니까 지양해야 한다던가..
- select * 은 하면 안 되고, 필요한 것만 지정해서 select 해야 한다던가..
- order by 사용하는 컬럼에 index 를 추가한다던가
사실 내가 잘못하는 거일 수도 있는데.. 실무에서 생각보다 쿼리 EXPLAIN 을 쓸 일이 거의 없었다.
예전에는 평균 동접자 3000명 정도의 서비스를 고도화 한 적 있었는데
그때는 레거시 코드로 인한 쿼리 이슈가 꽤 많이 터져서 slow query 들을 식별하고
쿼리 실행 계획을 매번 확인해보며 여러가지 개선해 나갔던 것 같다
(이렇게 쿼리를 개선해서 속도가 빨라지면 무척이나 재밌었던 것으로 기억..하하)
하지만 그 이후에는 정부과제용으로 제출할 서비스 혹은 동접자가 많이 없는 B2B 서비스만 개발하게 되면서
쿼리 실행속도에는 크게 신경을 안 쓰고 쿼리 가독성에 더 집중했던 것 같다.
예를 들자면 하나의 쿼리에 무자비하게 leftJoin 하는 것을 지양하고,
DB 조회를 위한 i/o 가 많아지더라도 최대한 쿼리를 분리하고 비즈니스 로직 단에서 합친다던가.. -
그런데 아주 아주 오랜만에 EXPLAIN 을 사용할 일이 생겼다 🤓

학부 시절에 EXPLAIN 결과에서 type 컬럼만 보면 된다는 것을 주워들어서(?)
type 과 쿼리별 실행 속도를 기준으로 쿼리 튜닝 여부를 결정했다.
그래서 ref, eq_ref 타입이면 조인이 적절하게 되어있다는 소리니까 넘어가려고 하는데~..
Extra 에 Using filesort 가 나오면 개선 필요성이 있는 쿼리라는 신호이다.
(2년전에 사실 이 개념 알았는데 자주 사용 안 하니까 고새 까먹음 ㅠ.ㅠ)
*Using filesort: 정렬 작업이 메모리가 아닌 디스크에서 수행됨
왜 메모리가 아닌 디스크에서 수행이 된 걸까?
이유는 정렬해야 할 데이터의 크기가 메모리에 설정된 제한을 초과하기 때문이다
그럼 조회해오는 데이터의 크기를 줄여야 한다는건데..
페이징 처리는 당연히 되어있는 상태이므로 여기서 더 조회해올 데이터 크기를 줄일 순 없었다.
그래서 order by 컬럼에 인덱스를 추가해놓는게 하나의 개선 방법이다.
인덱스를 추가하면 왜 Using filesort 가 발생 안 하는걸까?
order by 컬럼을 인덱스로 지정하면
데이터 정렬이 쿼리를 실행하는 시점에 이루어지는 것이 아니라,
인덱스를 생성하는 과정에서 이미 정렬된 상태로 저장이 되기 때문이다.
그래서 쿼리 실행 시점에는 이미 정렬된 데이터를 순서대로 읽어오기만 하면 되니까 빠를 수밖에 없다.

인덱스를 추가한 후에는 더 이상 Using filesort 가 아닌, Backward index scan 이 적용된 걸 볼 수 있다.