<aside> ✉️ [email protected]
</aside>
안녕하세요, 사람인에 재직 중인 백엔드 개발자 이현재입니다.
CTO인 IT연구소장님께 개별 면담을 통해 사람인에서 **「개발 큐레이션」**이라는 이름으로 사내 정기 메일링을 진행하고 있습니다. 담당하고 있는 빌링 서비스 개발과 별도 업무로써 인정 받는 활동입니다. 사람인에이치알에 대해 대외적으로 알려진게 많지 않아 CTO 허락 하에 이번 챕터를 외부 공유드립니다.
요즘 프론트, 백엔드 막론하고 SQL은 기본이잖아요? 하다못해 기획자들에게도 조회용 DB를 공개하고 있습니다. SQL이 프로그래밍 언어 중 접근성이 제일 좋다지만, 사실 SQL도 알고 보면 굉장히 심오한 언어입니다. 쿼리를 짜면서 성능 이슈를 겪어보신 분 있으시죠? 이번에 대외적으로 공유 드릴 **「개발 큐레이션」**은 MySQL과 쿼리 최적화입니다.
데이터베이스에서 두 문자열을 비교할 때 서로 길이가 다르다면 효율을 위해 'a' = 'a '를 true 로 반환해요. 얼핏 보면 이상하지만, PAD/NON-PAD 방식 중 무엇을 채택하는지에 따라 DB마다 차이를 보입니다. MySQL과 달리 PostgreSQL는 false로 반환하네요!
SELECT 'eq' FROM dual WHERE 'a' = 'a ' // result "eq"
MySQL에서 'a' = 'a '가 true로 평가된다? - 우아한형제들 기술 블로그
지금부터 4년 전, 사람인 내부 세미나로 EXPLAIN에 대해 알아봤어요. EXPLAIN은 쿼리가 어떻게 동작하게 될지 실행계획을 살펴보는 함수죠. 조건절이 인덱스를 타지 않거나, 성능이 생각만큼 나오지 않을 때 실행계획을 분석하여 쿼리를 개선할 수 있어요.
EXPLAIN SELECT * FROM TABLE_NAME;
커버링 인덱스는 B-tree를 이용한 대용량 데이터 조회 방법입니다. 마찬가지로 4년 전, 사람인 개발자 한 분이 공유해주셨죠. 다만 그 글은 지나치게 간소화된 내용이라 추가 자료를 가져왔습니다. 예상했던 성능이 나오지 않는다면 커버링 인덱스를 활용해보세요.
// before
SELECT * FROM usertest WHERE chgdate LIKE '2012%' LIMIT 100000, 100;
// after
SELECT a.*
FROM (
SELECT userno
FROM usertest
WHERE chgdate LIKE '2012%'
limit 100000, 100
) b
JOIN usertest a ON b.userno = a.userno;
MySQL에서 커버링 인덱스로 쿼리 성능을 높여보자!!
재작년, 사람인 프로젝트를 진행하다가 성능 이슈로 직접 쿼리 튜닝하였습니다. 사내 DBA가 알려준 내용으로 잊지 않기 위해 정리해뒀죠. 참고 자료는 지인과 함께 운영하는 팀블로그에 올려둔 글입니다. 다만 지금은 직접 만들어 쓰는 위지윅에디터부터 서버까지 전부 재단장 중이라 글이 이쁘게 보이지 않네요.(도큐먼트 포멧까지 변경하다보니...) 그러니 편하게 보실 분은 노션으로 보세요.
// before
SELECT * FROM sample_data GROUP BY part_cd ORDER BY idx DESC;
// after
SELECT base.*
FROM ( SELECT *,
@seq := CASE WHEN @part_chk = part_cd THEN @seq + 1 ELSE 1 END AS seq,
@part_chk := part_cd AS checked
FROM sample_data
) AS base, (SELECT @part_chk := 0, @seq := 0) AS tmp
WHERE base.seq = 1
ORDER BY base.idx DESC;