JSCODE Logo
JSCODE 박재성JSCODE 제이온JSCODE 시니
과외유튜브블로그후기
완강 후기 이벤트블로그 리뷰 이벤트AWS SAA 합격 후기 이벤트
회사명 : JSCODE대표 : 박재성사업자 등록번호 : 244-22-01557통신판매업 : 제 2023-인천미추홀-0381 호

서울특별시 구로구 경인로 20가길 11(오류동, 아델리아)

Copyright ⓒ 2026 JSCODE - 최상위 현업 개발자들의 프로그래밍 교육 All rights reserved.

이용약관개인정보처리방침

비전공자도 이해할 수 있는 MySQL 성능 최적화 입문/실전 (SQL 튜닝편)

MySQL 성능 최적화를 본격적으로 배우기 전에!

신입 백엔드 면접에서 자주 물어보는 ‘DB 성능 최적화’ 경험?!
DB 성능 개선할 때 ‘SQL 튜닝’을 가장 먼저 해야 하는 이유 (vs 스케일업, 레플리케이션, 샤딩, 캐싱)
성능 개선을 위한 MySQL 구조 파악 / SQL 튜닝의 핵심

인덱스(Index) 기본 개념 / 실전 활용법

인덱스(Index)란?
[실습] 인덱스 직접 설정해보기 / 성능 측정해보기
기본으로 설정되는 인덱스 (PK)
제약 조건을 추가하면 자동으로 생성되는 인덱스 (UNIQUE)
[실습] 인덱스를 무식하게 많이 걸면 어떻게 될까?
멀티 컬럼 인덱스 (Mulitple-Column Index)란?
[실습] 멀티 컬럼 인덱스 직접 설정해보기 / 작동방식 이해하기
멀티 컬럼 인덱스 생성 시 주의점
커버링 인덱스(Covering Index)란?

실행 계획(EXPLAIN)을 활용해 성능 저하 요인 찾아내기

SQL문의 ‘실행 계획’ 사용해보기 (EXPLAIN)
실행 계획에서 type 의미 분석하기 (ALL, index)
실행 계획에서 type 의미 분석하기 (const, range, ref)

SQL문 튜닝 연습하기

[실습] 한 번에 너무 많은 데이터를 조회하는 SQL문 튜닝하기
[실습] WHERE문이 사용된 SQL문 튜닝하기 - 1
[실습] WHERE문이 사용된 SQL문 튜닝하기 - 2
[실습] 인덱스를 걸었는데도 인덱스가 작동하지 않는 경우 - 1
[실습] 인덱스를 걸었는데도 인덱스가 작동하지 않는 경우 - 2
[실습] ORDER BY문이 사용된 SQL문 튜닝하기
[실습] WHERE문에 인덱스를 걸기 vs ORDER BY문에 인덱스를 걸기
[실습] HAVING문이 사용된 SQL문 튜닝하기

실전 SQL문으로 튜닝 직접 해보기

[실습] 유저 이름으로 특정 기간에 작성된 글 검색하는 SQL문 튜닝하기
[실습] 특정 부서에서 최대 연봉을 가진 사용자들 조회하는 SQL문 튜닝하기
[실습] 부서별 최대 연봉을 가진 사용자들 조회하는 SQL문 튜닝하기
[실습] 2023년 주문 데이터 조회하는 SQL문 튜닝하기
[실습] 2024년 1학기 평균 성적이 100점인 학생 조회하는 SQL문 튜닝하기
[실습] 좋아요 많은 순으로 게시글 조회하는 SQL문 튜닝하기
← 블로그 목록으로 돌아가기

실행 계획에서 type 의미 분석하기 (const, range, ref)

JSCODE 박재성
JSCODE 박재성
2026. 03. 24.
author
JSCODE 박재성
category
MySQL
createdAt
Dec 2, 2025 10:02 AM
isPublic
isPublic
series
비전공자도 이해할 수 있는 MySQL 성능 최적화 입문/실전 (SQL 튜닝편)
slug
explain-type-const-range-ref
type
post
updatedAt
Mar 24, 2026 09:00

✅ const : 1건의 데이터를 바로 찾을 수 있는 경우

출처 : 업무에 바로 쓰는 SQL 튜닝 (책)
출처 : 업무에 바로 쓰는 SQL 튜닝 (책)
조회하고자 하는 1건의 데이터를 헤매지 않고 단번에 찾아올 수 있을 때 const가 출력된다. 그러다보니 고유 인덱스 또는 기본 키를 사용해서 1건의 데이터만 조회한 경우에 const가 출력된다. 이 방식은 아주 효율적인 방식이다.
 
외우지 말고 머릿속으로 이해해보자.
  • 인덱스가 없다면 특정 값을 일일이 다 뒤져야 한다. 그래서 1건의 데이터를 바로 찾을 수 없다.
  • 인덱스가 있는데 고유하지 않다면(NOT UNIQUE) 원하는 1건의 데이터를 찾았다고 하더라도, 나머지 데이터에 같은 값이 있을 지도 모르므로 다른 데이터들도 체크해봐야 한다.
  • 고유하다면(UNIQUE) 1건의 데이터를 찾는 순간, 나머지 데이터는 아예 볼 필요가 없어진다. 왜냐하면 찾고자 하는 데이터가 유일한 데이터이기 때문이다. → 고유 인덱스와 기본 키는 전부 UNIQUE한 특성을 가지고 있다.
 
[예제]
  1. 테이블 생성하기
    1. DROP TABLE IF EXISTS users; # 기존 테이블 삭제 CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, account VARCHAR(100) UNIQUE );
 
  1. 더미 데이터 넣기
    1. INSERT INTO users (account) VALUES ('user1@example.com'), ('user2@example.com'), ('user3@example.com');
 
  1. 실행 계획 조회하기
    1. EXPLAIN SELECT * FROM users WHERE id = 3; EXPLAIN SELECT * FROM users WHERE account = 'user3@example.com';
      • UNIQUE 속성을 가진 컬럼은 인덱스가 자동으로 생성된다.
        • 📖
          제약 조건을 추가하면 자동으로 생성되는 인덱스 (UNIQUE)
 
 

✅ range : 인덱스 레인지 스캔 (Index Range Scan)

인덱스 레인지 스캔(Index Range Scan)은 인덱스를 활용해 범위 형태의 데이터를 조회한 경우를 의미한다. 범위 형태란 BETWEEN, 부등호(<, >, ≤, ≥), IN, LIKE를 활용한 데이터 조회를 뜻한다.
이 방식은 인덱스를 활용하기 때문에 효율적인 방식이다. 하지만 인덱스를 사용하더라도 데이터를 조회하는 범위가 클 경우 성능 저하의 원인이 되기도 한다.
출처 : 업무에 바로 쓰는 SQL 튜닝 (책)
출처 : 업무에 바로 쓰는 SQL 튜닝 (책)
 
[예제]
  1. 테이블 생성하기
    1. DROP TABLE IF EXISTS users; CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, age INT );
 
  1. 더미 데이터 넣기
    1. -- 높은 재귀(반복) 횟수를 허용하도록 설정 -- (아래에서 생성할 더미 데이터의 개수와 맞춰서 작성하면 된다.) SET SESSION cte_max_recursion_depth = 1000000; -- 더미 데이터 삽입 쿼리 INSERT INTO users (age) WITH RECURSIVE cte (n) AS ( SELECT 1 UNION ALL SELECT n + 1 FROM cte WHERE n < 1000000 -- 생성하고 싶은 더미 데이터의 개수 ) SELECT FLOOR(1 + RAND() * 1000) AS age -- 1부터 1000 사이의 난수로 나이 생성 FROM cte;
       
  1. 인덱스 생성하기
    1. CREATE INDEX idx_age ON users(age);
 
  1. 실행 계획 조회하기
    1. EXPLAIN SELECT * FROM users WHERE age BETWEEN 10 and 20; EXPLAIN SELECT * FROM users WHERE age IN (10, 20, 30); EXPLAIN SELECT * FROM users WHERE age < 20;
 
 

✅ ref : 비고유 인덱스를 활용하는 경우

비고유 인덱스를 사용한 경우 (= UNIQUE가 아닌 컬럼의 인덱스를 사용한 경우) type에 ref가 출력된다.
출처 : 업무에 바로 쓰는 SQL 튜닝 (책)
출처 : 업무에 바로 쓰는 SQL 튜닝 (책)
 
  1. 테이블 생성하기
    1. DROP TABLE IF EXISTS users; # 기존 테이블 삭제 CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100) );
 
  1. 더미 데이터 넣기
    1. INSERT INTO users (name) VALUES ('박재성'), ('김지현'), ('이지훈');
 
  1. 인덱스 생성하기
    1. CREATE INDEX idx_name ON users(name);
       
  1. 실행 계획 조회하기
    1. EXPLAIN SELECT * FROM users WHERE name = '박재성';
 
 

✅ 이 외의 type들

eq_ref, index_merge, ref_or_null 등 다양한 타입들이 존재한다. 하지만 모든 타입들을 다 미리 공부할 필요는 없다. 자주 나오는 type에 먼저 익숙해진 다음에 더 깊이 공부하고 싶을 때 다른 type들도 찾아서 공부하면 된다.
📎
이 글은 비전공자도 이해할 수 있는 MySQL 성능 최적화 입문/실전 (SQL 튜닝편) 강의의 수업 자료 중 일부입니다.