---
title: "MySQL Partitioning 개요: RANGE·LIST·HASH·KEY 파티션의 목적과 한계"
description: "MySQL 파티션의 행 배치와 pruning 원리를 살펴보고, RANGE·LIST·HASH·KEY 선택 기준과 고유키·보관 정책의 제약을 실행 예제로 확인한다."
tags: [ MySQL, 아키텍처, 성능최적화, 운영 ]
image: "mysql-report-bg.png"
published: "2026-10-18"
updated: "2026-10-18"
author: "MySQL 기술 노트"
source_url: ""
---

테이블이 커졌다는 이유만으로 파티션을 도입하면 성능 문제는 남고 스키마 제약과 운영 절차만 늘어날 수 있다. 파티션은 **하나의 논리 테이블에 속한 행을 규칙에 따라 여러 물리 단위로 나누는 기능**이다. 오래된 데이터의 일괄 제거와 검색 범위 축소에 유용하지만, 인덱스나 서버 증설을 대신하지 않는다.

이 글은 Community MySQL 8.0 이상과 InnoDB를 기준으로 네 가지 파티션 방식의 목적을 구분한다. SQL은 폐기용 MySQL 8.0 인스턴스에서 실행한 소규모 기능 시험이며, 성능 수치나 운영 규모에서의 DDL 완료 시간을 증명하는 실험은 아니다. Aurora MySQL의 실제 클러스터 시험과 MySQL 8.4 실행 시험은 수행하지 않았다. 예제는 빈 실습 스키마에서 순서대로 실행하며, 6절에서 첫 번째 테이블을 정리한다.

## 1. 파티션이 바꾸는 것과 바꾸지 않는 것

InnoDB 파티션 테이블은 논리적으로 하나의 테이블이지만 파티션마다 데이터와 인덱스가 나뉜다. 각 파티션의 클러스터 인덱스와 보조 인덱스에서 행을 찾으며, 테이블 전체를 한 번에 탐색하는 별도의 전역 보조 인덱스가 생기는 것은 아니다. 따라서 파티션 키 조건 없이 보조 인덱스만 조회하면 여러 파티션의 인덱스를 각각 확인해야 할 수 있다.

조회에서는 다음 두 단계를 구분해야 한다.

- **Partition pruning:** 조건으로 결과가 존재할 수 없는 파티션을 제외한다. 검색 대상 파티션의 수를 줄이는 단계다.
- **파티션 내부 접근:** 남은 파티션에서 어떤 인덱스와 접근 방식을 사용할지 결정한다. pruning이 성공해도 내부에서 많은 행을 읽을 수 있다.

```mermaid
flowchart TD
    Q[SQL 조건과 테이블 정의] --> P{파티션 제외 가능 여부}
    P -->|가능| S[일부 파티션 선택]
    P -->|불가능| A[전체 파티션 검토]
    S --> I[각 대상 파티션의 인덱스 또는 테이블 스캔]
    A --> I
    I --> R[조건 평가 및 필요한 정렬과 집계]
    R --> O[최종 결과 반환]
```

이 그림은 논리적인 접근 관계이며 실행기의 모든 단계를 시간 순서대로 나타낸 것은 아니다. 파티션 수만큼 쿼리가 자동 병렬화된다는 의미도 아니다. Community MySQL의 일반 InnoDB 파티션은 데이터를 여러 서버로 분산하는 샤딩이 아니며, CPU·버퍼 풀·로그·접속 처리 자원을 같은 서버에서 사용한다.

## 2. 네 가지 방식은 서로 다른 질문에 답한다

### RANGE: 경계를 기준으로 데이터 수명을 관리한다

RANGE는 정수식의 결과를 상한 경계로 나눈다. 날짜를 직접 경계로 표현하려면 `RANGE COLUMNS(date_col)`이 읽기 쉽다. `VALUES LESS THAN`은 상한을 포함하지 않으며, 첫 파티션은 정의된 첫 상한보다 작은 모든 값을 받는다. 파티션 이름이 `p202601`이라고 해서 자동으로 1월만 허용하는 것은 아니다.

시간 범위 조회와 월별 보관 만료 처리처럼 **조회 경계와 제거 경계가 일치할 때** 적합하다. 반대로 모든 신규 쓰기가 최신 파티션으로 몰리는 현상은 RANGE만으로 해결되지 않는다.

마지막에 `MAXVALUE` 파티션이 없으면 최대 경계를 넘는 행의 입력이 실패할 수 있다. `MAXVALUE`는 입력 여유를 주지만 다음 기간 파티션을 자동 생성하지 않는다. 이를 두었다면 일반적으로 그 파티션을 `REORGANIZE PARTITION`으로 나누어 새로운 경계를 만든다. 이때 이미 쌓인 행의 재배치 비용까지 고려해야 한다.

### LIST: 명시적인 값 집합으로 업무 영역을 묶는다

LIST는 정수값 목록, `LIST COLUMNS`는 허용된 자료형의 컬럼값 목록으로 행을 분류한다. 지역 코드나 업무 구분처럼 **관리 대상 집합이 작고 명확할 때** 유용하다. 값은 서로 중복된 파티션에 속할 수 없다.

MySQL LIST에는 임의의 새 값을 받아 주는 일반적인 `DEFAULT` 파티션이 없다. 목록 밖의 코드가 유입되면 입력이 실패하므로 애플리케이션 코드 추가와 파티션 정의 변경 순서를 맞춰야 한다. 지역별 행 수나 쓰기 빈도가 크게 다르면 파티션도 불균등해진다.

### HASH: 사용자가 정한 정수식을 분산 규칙으로 쓴다

일반 HASH는 지정한 정수식과 파티션 수를 이용해 배치한다. 양의 정수 키를 사용하는 예제에서는 `MOD(키, 파티션 수)`로 배치를 이해할 수 있다. 식의 계산 비용은 쓰기 경로에도 영향을 주므로 복잡한 식은 피한다.

HASH는 날짜별 일괄 제거보다 여러 키값을 나누는 목적에 가깝다. 같은 고객의 행은 같은 결과값으로 모이므로 대형 고객 하나가 부하 대부분을 만드는 문제까지 해결하지는 않는다. 파티션 수 변경은 기존 행의 재분배를 수반할 수 있다. `LINEAR HASH`는 다른 배치 알고리즘이므로 일반 HASH와 변경 비용·분포를 동일하게 보아서는 안 된다.

### KEY: MySQL의 내부 해시로 컬럼값을 나눈다

KEY는 사용자가 해시식을 작성하는 대신 컬럼 목록을 지정한다. 정수 외에 문자열 등도 사용할 수 있지만 모든 자료형이 허용되는 것은 아니며, `TEXT`·`BLOB` 등의 제약을 확인해야 한다. `KEY()`처럼 컬럼을 생략하는 문법도 있으나 운영 정의에는 의도를 드러내도록 명시하는 편이 낫다.

KEY의 배치를 `MOD(컬럼값, 파티션 수)`로 추정하거나 InnoDB에서 MD5를 사용한다고 단정하지 않는다. 애플리케이션에 내부 해시 계산을 복제해 특정 파티션 번호를 고정하는 설계도 피한다. HASH·KEY의 pruning은 식·자료형·조건 형태에 제약이 있으므로 실제 `EXPLAIN`으로 확인해야 한다. 아래 실습은 정수 키의 단순 동등 조건을 사용한다.

## 3. RANGE 실습: 파티션 선택과 인덱스 선택을 따로 읽는다

다음 테이블은 날짜를 파티션 키로, `(id, occurred_on)`을 기본 키로 사용한다. 같은 `id`가 서로 다른 날짜에 등장하도록 의도적으로 데이터를 넣었다. 보조 인덱스의 필요성을 배제하지 않으면서 파티션 선택만 비교하기 위해 작은 데이터와 Traditional `EXPLAIN`을 사용한다.

```sql
CREATE TABLE part_event (
    id BIGINT NOT NULL,
    occurred_on DATE NOT NULL,
    amount INT NOT NULL,
    PRIMARY KEY (id, occurred_on)
) ENGINE=InnoDB
PARTITION BY RANGE COLUMNS(occurred_on) (
    PARTITION p202601 VALUES LESS THAN ('2026-02-01'),
    PARTITION p202602 VALUES LESS THAN ('2026-03-01'),
    PARTITION p_future VALUES LESS THAN (MAXVALUE)
);
INSERT INTO part_event VALUES
    (1, '2026-01-15', 100), (1, '2026-02-15', 200),
    (2, '2026-02-20', 300), (3, '2026-03-05', 400);
EXPLAIN SELECT id, amount FROM part_event
WHERE occurred_on >= '2026-02-01' AND occurred_on < '2026-03-01';
EXPLAIN SELECT id, amount FROM part_event WHERE id = 1;
SELECT id, COUNT(*) AS rows_per_id
FROM part_event GROUP BY id ORDER BY id;
```

실행 결과(MySQL 8.0.x):

준비 SQL을 축약하고 `EXPLAIN`은 핵심 열만 발췌했다. 실제 검증 버전은 MySQL 8.0.46이다.

```text
mysql> CREATE TABLE part_event ...;
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO part_event VALUES (...);
Query OK, 4 rows affected (0.01 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> EXPLAIN SELECT id, amount FROM part_event
    -> WHERE occurred_on >= '2026-02-01' AND occurred_on < '2026-03-01';
partitions: p202602
      type: ALL
       key: NULL
     Extra: Using where
1 row in set (0.00 sec)

mysql> EXPLAIN SELECT id, amount FROM part_event WHERE id = 1;
partitions: p202601,p202602,p_future
      type: ref
       key: PRIMARY
     Extra: NULL
1 row in set (0.00 sec)

mysql> SELECT id, COUNT(*) AS rows_per_id
    -> FROM part_event GROUP BY id ORDER BY id;
+----+-------------+
| id | rows_per_id |
+----+-------------+
|  1 |           2 |
|  2 |           1 |
|  3 |           1 |
+----+-------------+
3 rows in set (0.00 sec)
```

첫 번째 계획의 `partitions`는 `p202602`만 가리킨다. 다만 날짜가 기본 키의 선두 컬럼은 아니므로 이것이 곧 효율적인 날짜 인덱스 탐색을 의미하지는 않는다. 두 번째 계획은 `id`로 인덱스를 사용할 수 있어도 날짜 조건이 없어 여러 파티션을 검사한다. **인덱스를 사용한다는 사실과 pruning 성공 여부는 별개**다. 작은 표본의 `rows` 추정치를 운영 비용으로 환산하지 않는다.

또한 `id = 1`의 행이 두 개 존재한다. 날짜를 기본 키에 추가한 순간 유일성의 범위는 `id` 단독에서 `(id, occurred_on)` 조합으로 바뀐다. 파티션을 도입하기 위해 키만 늘리고 기존 업무 식별자의 전역 유일성이 보장된다고 생각하면 데이터 계약이 달라진다.

## 4. LIST·HASH·KEY 실습: 정의와 실제 배치를 확인한다

### LIST COLUMNS의 업무 코드 분리

```sql
CREATE TABLE part_region (
    id INT NOT NULL,
    region_code CHAR(2) CHARACTER SET ascii NOT NULL,
    PRIMARY KEY (id, region_code)
) ENGINE=InnoDB
PARTITION BY LIST COLUMNS(region_code) (
    PARTITION p_local VALUES IN ('KR'),
    PARTITION p_remote VALUES IN ('US', 'JP')
);
INSERT INTO part_region VALUES (1, 'KR'), (2, 'US'), (3, 'JP');
SELECT 'p_local' AS partition_name, COUNT(*) AS exact_rows
FROM part_region PARTITION (p_local)
UNION ALL
SELECT 'p_remote', COUNT(*) FROM part_region PARTITION (p_remote);
DROP TABLE part_region;
```

실행 결과(MySQL 8.0.x):

```text
mysql> CREATE TABLE part_region ...;

Query OK, 0 rows affected (0.01 sec)

mysql> INSERT INTO part_region VALUES (1, 'KR'), (2, 'US'), (3, 'JP');

Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> SELECT 'p_local' AS partition_name, COUNT(*) AS exact_rows
    -> FROM part_region PARTITION (p_local)
    -> UNION ALL
    -> SELECT 'p_remote', COUNT(*) FROM part_region PARTITION (p_remote);

+----------------+------------+
| partition_name | exact_rows |
+----------------+------------+
| p_local        |          1 |
| p_remote       |          2 |
+----------------+------------+
2 rows in set (0.01 sec)

mysql> DROP TABLE part_region;

Query OK, 0 rows affected (0.00 sec)
```

`PARTITION (...)`은 진단을 위해 대상 파티션을 직접 지정하는 문법이다. 자동 pruning을 시험한 결과는 아니다. 애플리케이션이 파티션 이름을 잘못 지정하면 조건에 맞는 다른 파티션의 행을 누락할 수 있으므로 일반 조회를 이 방식으로 바꾸는 것은 신중해야 한다.

### HASH와 KEY의 정수 키 동등 조건

```sql
CREATE TABLE part_hash (
    id INT NOT NULL PRIMARY KEY
) ENGINE=InnoDB PARTITION BY HASH(id) PARTITIONS 4;
CREATE TABLE part_key (
    id INT NOT NULL PRIMARY KEY
) ENGINE=InnoDB PARTITION BY KEY(id) PARTITIONS 4;
INSERT INTO part_hash VALUES (1), (2), (3), (4);
INSERT INTO part_key SELECT id FROM part_hash;
SELECT 'p0' AS partition_name, COUNT(*) AS exact_rows
FROM part_hash PARTITION (p0)
UNION ALL SELECT 'p1', COUNT(*) FROM part_hash PARTITION (p1)
UNION ALL SELECT 'p2', COUNT(*) FROM part_hash PARTITION (p2)
UNION ALL SELECT 'p3', COUNT(*) FROM part_hash PARTITION (p3);
EXPLAIN SELECT id FROM part_hash WHERE id = 3;
EXPLAIN SELECT id FROM part_key WHERE id = 3;
DROP TABLE part_hash, part_key;
```

실행 결과(MySQL 8.0.x):

준비 SQL과 집계 SQL의 표기를 줄이고 `EXPLAIN`은 핵심 열만 발췌했다.

```text
mysql> CREATE TABLE part_hash ...;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE part_key ...;
Query OK, 0 rows affected (0.01 sec)
mysql> INSERT INTO part_hash VALUES (1), (2), (3), (4);
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0
mysql> INSERT INTO part_key SELECT id FROM part_hash;
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> SELECT ... UNION ALL ...;
+----------------+------------+
| partition_name | exact_rows |
+----------------+------------+
| p0             |          1 |
| p1             |          1 |
| p2             |          1 |
| p3             |          1 |
+----------------+------------+
4 rows in set (0.00 sec)

mysql> EXPLAIN SELECT id FROM part_hash WHERE id = 3;
partitions: p3
      type: const
       key: PRIMARY
     Extra: Using index
1 row in set (0.00 sec)

mysql> EXPLAIN SELECT id FROM part_key WHERE id = 3;
partitions: p2
      type: const
       key: PRIMARY
     Extra: Using index
1 row in set (0.00 sec)

mysql> DROP TABLE part_hash, part_key;
Query OK, 0 rows affected (0.00 sec)
```

HASH의 행 수는 이 표본에서만 균등하다. 실제 데이터의 키 분포나 부하 분포가 균등하다는 증거는 아니다. 두 실행 계획에서는 각각 단일 파티션을 선택하는지 확인한다. KEY의 파티션 번호가 HASH와 같을 필요는 없으며, 번호 자체를 업무 규칙으로 사용하지 않는다.

운영 점검에서는 `information_schema.PARTITIONS`의 `PARTITION_NAME`, `PARTITION_METHOD`, `PARTITION_EXPRESSION`, `PARTITION_DESCRIPTION`으로 정의를 확인할 수 있다. 이 테이블의 InnoDB `TABLE_ROWS`는 정확한 행 수가 아니라 추정값이다. 위 실습은 `COUNT(*)`로 실제 행을 세지만, 대형 운영 테이블에서 같은 전수 집계를 상시 수행하라는 의미는 아니다.

## 5. 모든 고유키에 걸리는 제약을 먼저 검토한다

파티션 식에 사용한 모든 컬럼은 **모든 UNIQUE KEY와 PRIMARY KEY에 포함**되어야 한다. 기본 키만 수정하고 별도의 `UNIQUE(email)`을 그대로 두면 정의가 거부될 수 있다. 이는 파티션별 인덱스로 유일성을 검사하는 구조와 연결된다.

다음은 날짜로 파티션을 나누면서 기본 키에 날짜를 누락한 정의가 거부되는지 확인한다. 예상 오류를 처리하는 실습용 프로시저이며, 예상한 오류가 발생하지 않으면 `SIGNAL`로 검증 자체를 실패시킨다. 운영 오류를 무시하기 위한 패턴이 아니다.

```sql
DELIMITER //
CREATE PROCEDURE check_partition_key()
BEGIN
    DECLARE rejected INT DEFAULT 0;
    BEGIN
        DECLARE CONTINUE HANDLER FOR 1503 SET rejected = 1;
        CREATE TABLE part_bad_key (
            id INT NOT NULL PRIMARY KEY,
            occurred_on DATE NOT NULL
        ) ENGINE=InnoDB
        PARTITION BY RANGE COLUMNS(occurred_on) (
            PARTITION p0 VALUES LESS THAN (MAXVALUE)
        );
    END;
    IF rejected <> 1 THEN
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Expected error 1503';
    END IF;
    SELECT rejected AS unique_key_definition_rejected;
END//
DELIMITER ;
CALL check_partition_key();
DROP PROCEDURE check_partition_key;
```

실행 결과(MySQL 8.0.x):

```text
mysql> CREATE PROCEDURE check_partition_key() ...;

Query OK, 0 rows affected (0.00 sec)

mysql> CALL check_partition_key();

+--------------------------------+
| unique_key_definition_rejected |
+--------------------------------+
|                              1 |
+--------------------------------+
1 row in set (0.01 sec)

Query OK, 0 rows affected (0.01 sec)

mysql> DROP PROCEDURE check_partition_key;

Query OK, 0 rows affected (0.00 sec)
```

결과의 프로시저 정의는 중복을 피하려고 축약했다. 성공한 `CALL`은 내부 `CREATE TABLE`이 성공했다는 뜻이 아니라, 오류 1503을 실제로 받아 기대 조건을 통과했다는 뜻이다. 필요한 고유성 계약을 유지할 수 없다면 비파티션 테이블을 유지하거나 별도의 식별자 관리 모델을 설계해야 한다. 별도 테이블로 유일성을 관리하는 방안도 트랜잭션 경계와 동시성 검증이 추가로 필요하다.

InnoDB 파티션 테이블은 외래 키를 정의할 수 없고 다른 InnoDB 테이블의 외래 키 참조 대상이 될 수도 없다. `FULLTEXT` 등에도 제약이 있다. 파티션 도입 검토는 ALTER 문법 시험보다 먼저 기존 제약조건과 인덱스 목록을 조사하는 데서 시작한다.

## 6. RANGE 파티션 삭제는 보관 정책 전체가 아니다

`DROP PARTITION`은 해당 파티션의 행을 제거하고 정의도 없앤다. 행별 `DELETE`와 달리 파티션 단위로 데이터를 제거할 수 있지만, 메타데이터 잠금과 DDL 비용이 사라지는 것은 아니다. 완료된 삭제는 일반 트랜잭션의 `ROLLBACK`으로 복구할 수 없다. 실습용 테이블에서만 다음을 실행한다.

```sql
ALTER TABLE part_event DROP PARTITION p202601;
SELECT COUNT(*) AS remaining_rows FROM part_event;
INSERT INTO part_event VALUES (9, '2026-01-20', 900);
SELECT id, occurred_on FROM part_event PARTITION (p202602)
ORDER BY occurred_on, id;
DROP TABLE part_event;
```

실행 결과(MySQL 8.0.x):

```text
mysql> ALTER TABLE part_event DROP PARTITION p202601;

Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> SELECT COUNT(*) AS remaining_rows FROM part_event;

+----------------+
| remaining_rows |
+----------------+
|              3 |
+----------------+
1 row in set (0.00 sec)

mysql> INSERT INTO part_event VALUES (9, '2026-01-20', 900);

Query OK, 1 row affected (0.00 sec)

mysql> SELECT id, occurred_on FROM part_event PARTITION (p202602)
    -> ORDER BY occurred_on, id;

+----+-------------+
| id | occurred_on |
+----+-------------+
|  9 | 2026-01-20  |
|  1 | 2026-02-15  |
|  2 | 2026-02-20  |
+----+-------------+
3 rows in set (0.00 sec)

mysql> DROP TABLE part_event;

Query OK, 0 rows affected (0.01 sec)
```

삭제 직후에는 기존 1월 행이 제거된다. 그러나 첫 파티션을 삭제한 뒤 남은 첫 경계는 여전히 `'2026-03-01'`보다 작은 값 전체를 포괄한다. 따라서 뒤늦게 도착한 1월 행은 `p202602`에 들어간다. **파티션 삭제는 과거 날짜의 입력을 영구 거부하는 규칙이 아니다.** 이 차이는 지연 수집, 재처리, 백필이 있는 시스템에서 중요하다.

보관 정책에는 입력 허용 기간, 지연 데이터 처리, 삭제 대상 승인, 백업 보존을 함께 정의해야 한다. `TRUNCATE PARTITION`은 데이터만 비우고 파티션 정의를 남긴다는 점에서도 `DROP PARTITION`과 다르다. 두 작업을 이름만 보고 대체하지 않는다.

파티션을 많이 만들면 개별 단위는 작아지지만 메타데이터·파일·통계 관리와 다중 파티션 접근 비용이 증가할 수 있다. MySQL 8.4의 비NDB 테이블 상한은 서브파티션을 포함해 8192개지만, 이는 설계 권장값이 아니다. 날짜별 보관 단위를 먼저 정한 뒤 필요한 파티션 수를 산출한다.

## 7. Aurora MySQL에서 달라지는 운영 해석

Aurora의 분산 스토리지와 SQL 테이블 파티션은 서로 다른 계층이다. RANGE나 HASH를 추가했다고 파티션별로 writer가 생기거나 특정 reader가 특정 파티션을 전담하지 않는다. 파티션 pruning과 인덱스의 필요성, 데이터 수명에 맞춘 경계 설계는 여전히 SQL 계층의 문제다.

반면 Community의 로컬 데이터 파일 위치나 파일 삭제 시간을 Aurora에 그대로 적용해서는 안 된다. Aurora는 클러스터 볼륨을 사용하고 스토리지 용량의 증가·회수·과금은 엔진 버전과 스토리지 동작의 영향을 받는다. 파티션을 제거한 직후 청구 저장량도 즉시 같은 크기로 줄어든다고 단정하지 않는다.

실행 전에는 정확한 Aurora 엔진 버전에서 파티션 DDL 지원과 제한을 확인하고, 스테이징에서 MDL 대기·쓰기 지연·reader lag·스토리지 지표를 함께 관측한다. 이 글의 로컬 성공 결과는 Aurora에서 동일한 잠금 시간이나 복구 시간을 보장하지 않는다.

## 8. 도입 판단 체크리스트

- [ ] 목적이 보관 만료 처리인지, 특정 조회의 pruning인지, 키값 분산인지 구분했다.
- [ ] 대표 조회의 `EXPLAIN`에서 `partitions`와 `key`를 따로 확인했다.
- [ ] 파티션 키가 없는 조회와 전체 기간 집계의 비용도 비교했다.
- [ ] 모든 고유키에 파티션 컬럼을 넣어도 기존 업무 유일성 계약이 유지된다.
- [ ] 외래 키·FULLTEXT 등 기존 기능과 파티션 제약의 충돌을 조사했다.
- [ ] RANGE 경계와 지연 입력, LIST 신규 코드, NULL 처리 정책을 정했다.
- [ ] HASH·KEY의 키 분포뿐 아니라 특정 키의 쓰기 집중도도 확인했다.
- [ ] 경계 추가·재구성·만료 삭제 작업의 MDL 대기, 실패 중단 조건, 복구 절차를 시험했다.
- [ ] 파티션 삭제 후에도 백업 보관 기간과 지연 데이터 유입을 별도로 관리한다.
- [ ] Aurora에서는 실제 엔진 버전과 클러스터 지표로 검증을 보완한다.

## 9. 정리

파티션 방식의 선택은 테이블 크기보다 **데이터 수명, 조회 조건, 고유성 계약**에서 출발한다. RANGE는 경계 기반 수명 관리, LIST는 명시적 업무 집합, HASH와 KEY는 키 기반 배치에 초점이 있다. 어느 방식도 인덱스 설계와 SQL 검증을 생략하게 해주지 않는다.

다음 단계에서는 실제 시간 축에 맞춘 RANGE 경계 관리와 pruning이 실패하는 조건을 더 좁혀 살펴볼 수 있다. 우선 파티션을 적용하지 않은 설계를 기준선으로 두고, 얻는 이점과 추가되는 운영 의무를 함께 비교해야 한다.

### 참고 문서

- [MySQL 8.4: 파티션 개요](https://dev.mysql.com/doc/refman/8.4/en/partitioning-overview.html)
- [MySQL 8.4: HASH 파티션](https://dev.mysql.com/doc/refman/8.4/en/partitioning-hash.html)
- [MySQL 8.4: KEY 파티션](https://dev.mysql.com/doc/refman/8.4/en/partitioning-key.html)
- [MySQL 8.4: 파티션 pruning](https://dev.mysql.com/doc/refman/8.4/en/partitioning-pruning.html)
- [MySQL 8.4: 파티션과 고유키 제약](https://dev.mysql.com/doc/refman/8.4/en/partitioning-limitations-partitioning-keys-unique-keys.html)
- [MySQL 8.4: 파티션 제한 사항](https://dev.mysql.com/doc/refman/8.4/en/partitioning-limitations.html)
- [AWS: Aurora 스토리지와 신뢰성](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Aurora.Overview.StorageReliability.html)
