Backend
home

Join부터 트랜잭션까지, 성능과 안정성 잡기

생성 일시
2025/05/04 17:31
태그
MySQL
게시일
2025/05/05
최종 편집 일시
2025/05/04 17:45

1. JOIN - 단순 연결을 넘어선 전략적 활용이 필요

초기엔 INNER JOIN 이나 LEFT JOIN 정도로 끝났지만, 대량 데이터 환경 같은 경우 JOIN 순서와 드라이빙 테이블 선정이 성능에 결정적이다.
Small Table Driving: 작은 테이블을 먼저 읽고 큰 테이블과 조인하는 방식이 보통 더 효율적이다.
Index Nested Loop Join을 유도하려면 조인 컬럼에 인덱스가 걸려 있어야한다.
EXPLAIN 실행 계획에서 type 컬럼이 ALL로 나오면 풀 스캔이고, refconst가 나오도록 튜닝하는 걸 목표로 해야 한다.

2. 서브쿼리 vs JOIN - 성능은 종이 한 장 차이?

WHERE 절의 서브쿼리로는 간단히 데이터를 필터링할 수 있지만, 복잡해질수록 JOIN 방식으로 리팩토링하는 게 더 빠른 경우가 많았다.
In Subquery는 경우에 따라 Semi Join으로 최적화되지만, 서브쿼리 내부에서 LIMIT이나 ORDER BY를 사용하면 옵티마이저가 JOIN으로 변환하지 못한다.
서브쿼리는 간결하지만, 다량 데이터 필터링 시엔 항상 EXPLAIN으로 실행 계획을 비교해보고 JOIN 변환을 고려한다.

3. 인덱스 - 많다고 좋은 게 아니다

인덱스는 검색 속도를 올리지만, 쓰기 성능스토리지를 희생한다. 실무에선 다음을 기준으로 인덱스를 관리한다.
읽기가 많은 컬럼에만 인덱스를 부여
복합 인덱스는 컬럼 순서에 민감 (WHERE, ORDER BY 절의 순서와 일치해야 효율적)
Covering Index를 활용해 Using Index 만으로 결과를 가져오면 디스크 접근을 줄일 수 있다.
SHOW INDEX FROM 테이블명으로 현재 인덱스 현황을 파악하고, Slow Query Log 분석을 통해 인덱스가 필요한 쿼리를 선별한다.

4. SQL 튜닝 — 실행 계획은 거짓말을 하지 않는다

SQL 튜닝의 핵심은 실행 계획(Explain) 분석이다.
rows 값이 예상보다 크다면 인덱스가 제대로 동작하지 않는 것일 수 있다.
Using temporary; Using filesort 문구는 쿼리가 메모리 임시 테이블과 파일 정렬을 쓰고 있다는 신호이다.
튜닝 프로세스는 다음과 같다:
1.
EXPLAIN으로 문제 구간 식별
2.
인덱스 추가 혹은 쿼리 재작성
3.
테스트 데이터셋에서 재검증
ANALYZE TABLE, OPTIMIZE TABLE 명령어로 통계정보를 최신화해 옵티마이저가 더 나은 실행 계획을 선택하게 만든다.

5. 트랜잭션 - ACID는 여전히 중요하다.

트랜잭션은 단순히 BEGIN, COMMIT만 알면 끝나는 영역이 아니다. 특히 격리 수준 (Isolation Level)에 따라 서비스의 데이터 정합성과 성능이 크게 달라진다.
REPEATABLE READ (기본값): 팬텀 리드 방지하지만, 잠금 경쟁 심화 가능성
READ COMMITTED: 대부분의 서비스에서 실용적이며 잠금 문제를 줄여준다.
InnoDB 스토리지 엔진은 MVCC (다중 버전 동시성 제어)로 락 없이도 트랜잭션을 관리한다. 그러나 대용량 업데이트 시엔 Gap Lock, Next-Key Lock 이슈도 반드시 체크해야 한다.
ChatGPT 참고 (MySQL 서브쿼리, 인덱스, SQL 튜닝...)
Plain Text
복사