MySQL에서 가장 실무적으로 많이 쓰는 3가지 파티션 방식(월별 RANGE / 일자 RANGE / HASH) 기준으로 예제
설명 + 예제 + 쿼리 패턴까지 한 번에 이해되는 구성
CREATE TABLE transaction_log (
id BIGINT NOT NULL AUTO_INCREMENT,
user_id BIGINT NOT NULL,
amount INT NOT NULL,
created_at DATETIME NOT NULL,
PRIMARY KEY (id, created_at)
)
PARTITION BY RANGE (TO_DAYS(created_at)) (
PARTITION p202401 VALUES LESS THAN (TO_DAYS('2024-02-01')),
PARTITION p202402 VALUES LESS THAN (TO_DAYS('2024-03-01')),
PARTITION p202403 VALUES LESS THAN (TO_DAYS('2024-04-01')),
PARTITION pmax VALUES LESS THAN MAXVALUE
);
ALTER TABLE transaction_log
ADD PARTITION (
PARTITION p202404 VALUES LESS THAN (TO_DAYS('2024-05-01'))
);
→ 파티션은 미리 여러 달을 추가해두는 게 운영 편함.
ALTER TABLE transaction_log DROP PARTITION p202401;
→ 즉시 DROP, DELETE보다 수십~수천 배 빠름
→ Undo log 거의 없음
하루 수백만 건 이상 적재되는 테이블에 주로 사용.
CREATE TABLE access_log (
id BIGINT NOT NULL AUTO_INCREMENT,
ip VARCHAR(50),
created_at DATETIME NOT NULL,
PRIMARY KEY(id, created_at)
)
PARTITION BY RANGE (TO_DAYS(created_at)) (
PARTITION p20241201 VALUES LESS THAN (TO_DAYS('2024-12-02')),
PARTITION p20241202 VALUES LESS THAN (TO_DAYS('2024-12-03')),
PARTITION p20241203 VALUES LESS THAN (TO_DAYS('2024-12-04')),
PARTITION pmax VALUES LESS THAN MAXVALUE
);
ALTER TABLE access_log
ADD PARTITION (
PARTITION p20241204 VALUES LESS THAN (TO_DAYS('2024-12-05'))
);
보통 자동 스케줄러(CRON + SQL)로 매일 생성하는 방식 사용.
예:
CREATE TABLE user_log (
id BIGINT AUTO_INCREMENT,
user_id BIGINT NOT NULL,
action VARCHAR(100),
created_at DATETIME,
PRIMARY KEY(id)
)
PARTITION BY HASH(user_id)
PARTITIONS 8;
SELECT *
FROM transaction_log
WHERE created_at >= '2024-03-01'
AND created_at < '2024-04-01';
→ MySQL은 자동으로
p202403 파티션 하나만 스캔함
반대로 Pruning이 안 되는 패턴:
WHERE DATE(created_at) = '2024-03-05'
날짜 함수 씌우면 pruning 안 됨.
→ 반드시 컬럼에 함수 쓰면 안 됨
| 데이터 양 | 추천 |
| 1천만 건 이하 | 파티션 불필요 |
| 5천만 건 이상 | 월별 파티션 검토 |
| 1억 건 이상 | 월별 or 일별 강력추천 |
| 1억 ~ 10억 | 파티션 없으면 장애 수준 |
| 10억 이상 | 파티션 필수 + 압축 or 샤딩 고려 |
PARTITION BY RANGE (TO_DAYS(created_at)) (
PARTITION p20241201 VALUES LESS THAN (TO_DAYS('2024-12-02')),
PARTITION p20241202 VALUES LESS THAN (TO_DAYS('2024-12-03')),
PARTITION p20241203 VALUES LESS THAN (TO_DAYS('2024-12-04')),
PARTITION pmax VALUES LESS THAN MAXVALUE
);
이 문법은 MySQL에서 **"이 테이블은 날짜(created_at) 기준으로 여러 조각(파티션)으로 나누어 저장하겠다"**라는 의미입니다.
하나씩 뜯어보죠.
created_at은 DATETIME 타입입니다.
하지만 RANGE 파티션은 정수(Integer) 형태의 값을 기준으로 나누는게 가장 정확합니다.
그래서 MySQL에서 흔하게 두 가지를 사용합니다:
| 함수 | 의미 |
| TO_DAYS(datetime) | 날짜를 일수(정수)로 변환 |
| UNIX_TIMESTAMP(datetime) | 초 기반 정수 |
예:
TO_DAYS('2024-12-02') → 752350 같은 정수로 변환됩니다.
즉, 내부적으로는 이런 느낌:
created_at >= 2024-12-01 → TO_DAYS = 752349
created_at < 2024-12-02 → TO_DAYS = 752350
정수값 기준으로 나누니까 파티션 범위가 깔끔하게 동작합니다.
이 파티션은 특정 기준값보다 작은 데이터들을 저장한다라는 뜻입니다.
예를 들어:
PARTITION p20241201 VALUES LESS THAN (TO_DAYS('2024-12-02'))
이 파티션에는 2024-12-01 하루치 데이터만 들어갑니다.
왜냐?
즉:
p20241201 파티션 조건:
TO_DAYS(created_at) < 752350
→ created_at < 2024-12-02 00:00:00
따라서 2024-12-01 00:00:00 ~ 2024-12-01 23:59:59 범위 데이터만 저장됨.
전체 파티션 구간이 이렇게 연결되도록 구성해야 합니다.
p20241201 → created_at < 2024-12-02
p20241202 → created_at < 2024-12-03
p20241203 → created_at < 2024-12-04
RANGE 파티션은 다음 규칙이 있습니다:
✔ 각 파티션의 범위는 “LESS THAN” 기준
✔ 범위가 서로 겹쳐서는 안 됨
✔ 전체 범위가 끊어지면 안 됨
그래서 이렇게 연속해서 만들어야 합니다.
만약 새 날짜가 들어와도 해당하는 파티션이 없으면 insert 에러가 납니다.
예:
INSERT INTO logs(created_at) VALUES('2024-12-10');
그런데 2024-12-10 파티션을 미리 안 만들어놨다면 에러.
그래서 운영에서 반드시 MAXVALUE 마지막 파티션은 두는 게 안정적입니다.
INSERT INTO logs(created_at) VALUES('2024-12-01 12:00:00');
→ p20241201으로 들어감
(created_at < 2024-12-02에 해당)
INSERT INTO logs(created_at) VALUES('2024-12-03 07:00:00');
→ p20241203으로 들어감
(created_at < 2024-12-04에 해당)
INSERT INTO logs(created_at) VALUES('2025-01-01');
→ pmax로 들어감 (나머지 범위)

| /*+USE_IDX ORDERED*/ /*+USE_NL ORDERED*/ /*+USE_IDX*/ 인덱스 힌트 차이 (0) | 2025.12.17 |
|---|---|
| 쿼리 수행할때 중복제거 distinct 넣고 안넣고 플랜에서 차이 (0) | 2025.12.17 |
| 데이터베이스 테이블 파티션 partition 개념은? (0) | 2025.12.05 |
| 데이터 삭제 delete / truncate / partition drop 쓰는 방법 차이 (0) | 2025.12.05 |
| 데이터베이스 DELETE 트리거(Trigger)란? (0) | 2025.12.02 |