DROP TABLE IF EXISTS users; DROP TABLE IF EXISTS orders; CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE orders ( id INT AUTO_INCREMENT PRIMARY KEY, ordered_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, user_id INT, FOREIGN KEY (user_id) REFERENCES users(id) );
-- 높은 재귀(반복) 횟수를 허용하도록 설정 -- (아래에서 생성할 더미 데이터의 개수와 맞춰서 작성하면 된다.) SET SESSION cte_max_recursion_depth = 1000000; -- users 테이블에 더미 데이터 삽입 INSERT INTO users (name, 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자리 숫자로 구성된 이름 생성 TIMESTAMP(DATE_SUB(NOW(), INTERVAL FLOOR(RAND() * 3650) DAY) + INTERVAL FLOOR(RAND() * 86400) SECOND) AS created_at -- 최근 10년 내의 임의의 날짜와 시간 생성 FROM cte; -- orders 테이블에 더미 데이터 삽입 INSERT INTO orders (ordered_at, user_id) WITH RECURSIVE cte (n) AS ( SELECT 1 UNION ALL SELECT n + 1 FROM cte WHERE n < 1000000 -- 생성하고 싶은 더미 데이터의 개수 ) SELECT TIMESTAMP(DATE_SUB(NOW(), INTERVAL FLOOR(RAND() * 3650) DAY) + INTERVAL FLOOR(RAND() * 86400) SECOND) AS ordered_at, -- 최근 10년 내의 임의의 날짜와 시간 생성 FLOOR(1 + RAND() * 1000000) AS user_id -- 1부터 1000000 사이의 난수로 급여 생성 FROM cte;
SELECT * FROM orders WHERE YEAR(ordered_at) = 2023 ORDER BY ordered_at LIMIT 30;

EXPLAIN SELECT * FROM orders WHERE YEAR(ordered_at) = 2023 ORDER BY ordered_at LIMIT 30;

ordered_at에 인덱스를 추가하면 풀 테이블 스캔을 막을 수 있을 것 같다. 그래서 인덱스를 추가해보자. CREATE INDEX idx_ordered_at ON orders (ordered_at);


SELECT * FROM orders WHERE ordered_at >= '2023-01-01 00:00:00' AND ordered_at < '2024-01-01 00:00:00' ORDER BY ordered_at LIMIT 30;

