DROP TABLE IF EXISTS users;
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100),
department VARCHAR(100),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
100만 건의 랜덤 데이터 삽입
-- 높은 재귀(반복) 횟수를 허용하도록 설정
-- (아래에서 생성할 더미 데이터의 개수와 맞춰서 작성하면 된다.)
SET SESSION cte_max_recursion_depth = 1000000;
-- 더미 데이터 삽입 쿼리
INSERT INTO users (name, department, created_at)
WITH RECURSIVE cte (n) AS
(
SELECT 1
UNION ALL
SELECT n + 1 FROM cte WHERE n < 1000000 -- 생성하고 싶은 더미 데이터의 개수
)
SELECT
CONCAT('User', LPAD(n, 7, '0')) AS name, -- 'User' 다음에 7자리 숫자로 구성된 이름 생성
CASE
WHEN n % 10 = 1 THEN 'Engineering'
WHEN n % 10 = 2 THEN 'Marketing'
WHEN n % 10 = 3 THEN 'Sales'
WHEN n % 10 = 4 THEN 'Finance'
WHEN n % 10 = 5 THEN 'HR'
WHEN n % 10 = 6 THEN 'Operations'
WHEN n % 10 = 7 THEN 'IT'
WHEN n % 10 = 8 THEN 'Customer Service'
WHEN n % 10 = 9 THEN 'Research and Development'
ELSE 'Product Management'
END AS department, -- 의미 있는 단어 조합으로 부서 이름 생성
TIMESTAMP(DATE_SUB(NOW(), INTERVAL FLOOR(RAND() * 3650) DAY) + INTERVAL FLOOR(RAND() * 86400) SECOND) AS created_at -- 최근 10년 내의 임의의 날짜와 시간 생성
FROM cte;
-- 잘 생성됐는 지 확인
SELECT COUNT(*) FROM users;
SELECT * FROM users LIMIT 10;
데이터 조회해서 성능 측정하기
SELECT * FROM users
WHERE created_at >= DATE_SUB(NOW(), INTERVAL 3 DAY);
약 200ms 정도의 시간이 걸린다.
실행 계획 조회해보기
EXPLAIN SELECT * FROM users
WHERE created_at >= DATE_SUB(NOW(), INTERVAL 3 DAY);
type이 ALL이고 rows가 997,632인 걸 보니, 전체 데이터를 처음부터 끝까지 다 뒤져서 데이터를 찾아내는 풀 테이블 스캔을 했다. 풀 테이블 스캔은 성능상으로 비효율적이다.
출처 : 업무에 바로 쓰는 SQL 튜닝 (책)
성능 개선을 위한 인덱스 추가
created_at이 만약 정렬이 되어 있다면 최근 3일 이내에 가입한 유저를 훨씬 빠르게 조회할 수 있을 것이다. 그래서 created_at을 기준으로 정렬을 시키게끔 도와주는 인덱스를 추가해보자.
CREATE INDEX idx_created_at ON users (created_at);
SHOW INDEX FROM users;
데이터 조회해서 성능 측정하기
SELECT * FROM users
WHERE created_at >= DATE_SUB(NOW(), INTERVAL 3 DAY);
약 50ms 정도의 시간이 걸린다. 10배 정도 성능이 향상됐다.
실행 계획 조회해보기
EXPLAIN SELECT * FROM users
WHERE created_at >= DATE_SUB(NOW(), INTERVAL 3 DAY);
type이 range인걸로 봐서 인덱스 레인지 스캔 (Index Range Scan)을 했음을 알 수 있다.
출처 : 업무에 바로 쓰는 SQL 튜닝 (책)
⭐
[이것만은 꼭 기억해두자!]WHERE문의 부등호(>, <, ≤, ≥, =), IN, BETWEEN, LIKE와 같은 곳에서 사용되는 컬럼은 인덱스를 사용했을 때 성능이 향상될 가능성이 높다.