Skip to content
GwiyeomGo Tech Blog
About GwiyeomGo

mysql Query Plan

MYSQL, 20254 min read

배경

쿼리플랜을 실무에서 어떻게 봐야하나 항상 고민했다 슬로우 쿼리를 개선하고 업무로써 경험하고 싶었는데 기초적인 내용 이지만 기록하려고 한다 api 에서 멤버의 배지가 없는 경우만 추가하도록 기능을 수정해야 했다 단순히 존재 여부만 확인하는 쿼리였고 어떤 쿼리를 써야 좋을지 EXPLAIN 추가해서 인덱스를 타는지 조회속도를 비교해봤다

복합 인덱스 vs 단일 인덱스 vs count(*)로 1건 조회 한 경우 어떤 경우가 빠를까?

-- 복합 유니크 인덱스
SELECT 1 FROM user_contents WHERE member_id=1 AND content_id=2 LIMIT 1;
-- ✅ 단일 인덱스 활용
SELECT 1 FROM user_contents WHERE title_id=2 LIMIT 1;
-- ✅ count(*)로 조건 만족하는 행 개수 조회
SELECT count(*) FROM user_contents WHERE title_id=2;
  • COUNT(*)는 모든 행 스캔 발생 가능

EXPLAIN SELECT 1 FROM user_contents WHERE member_id=1 AND content_id=2 LIMIT 1;

+----+-------------+-------------+-------+-------------------------------------------+-------+------+------+------+ | id | select_type | table | type | key | ref | rows | Extra | +----+-------------+-------------+-------+-------------------------------------------+-------+------+------+------+ | 1 | SIMPLE | user_contents | const | idx_user_contents_member_id_content_id | const | 1 | Using index | +----+-------------+-------------+-------+-------------------------------------------+-------+------+------+------+

  • type const는 가장 효율적인 조회 방식,건에 맞는 값을 하나만 찾을 때 발생
  • key 인덱스가 사용됨
  • rows가 1로 효율적인 조회
  • Extra의 Using index는 인덱스를 사용해 쿼리가 실행되었음

EXPLAIN SELECT 1 FROM user_contents WHERE title_id=2 LIMIT 1; EXPLAIN SELECT count(*) FROM user_contents WHERE title_id=2;

+----+-------------+---------------+-------+-----------------------------+-----------------------+ | id | select_type | table | type | key | ref | Extra | +----+-------------+---------------+-------+---------------------------------------+-------------+ | 1 | SIMPLE | user_contents | ref | idx_user_contents_title_id | const | Using index | +----+-------------+---------------+-------+-----------------------------+---------+-------------+

  • type: ref: title_id 컬럼에 인덱스가 적용되어 조건이 빠르게 필터

  • Extra: Using index: 인덱스를 사용해서 데이터를 가져오는 방식으로 효율적

  • EXPLAIN 실행 계획을 확인할 때, Type 필드 const (상수 탐색, 가장 빠름) 상수처럼 결과적으로 한 번의 조회만으로 즉시 결과 반환 가능,완전히 특정된 유일한 row만 나옴 (O(1) 검색 가능) *ref (부분 인덱스 탐색) 인덱스를 사용하지만 여러 개의 row가 나올 가능성이 있음

결론

복합 인덱스 (특히 const 타입): 가장 빠르고 최적화된 조회 방식으로, 유일한 데이터를 빠르게 찾아낼 수 있습니다.

단일 인덱스: 데이터가 적당히 적을 때는 효율적이지만, 많은 데이터가 있을 경우 성능 저하가 발생할 수 있습니다.

COUNT(*): 조건에 맞는 행의 수를 구할 때 전체 테이블을 스캔하게 되어, 대규모 테이블에서는 성능이 저하될 수 있습니다. 인덱스를 잘 활용하면 성능 개선이 가능하지만, 조건에 맞는 데이터가 많을 경우 성능 이슈가 발생할 수 있습니다.

데이터의 양과 쿼리 조건에 따라 적절한 인덱스를 선택하는 것이 중요하며 가능한 한 복합 인덱스를 활용하여 성능을 최적화하는 것이 좋다

참고

https://harris91.vercel.app/query-plan

© 2025 by GwiyeomGo Tech Blog. All rights reserved.