주문 테이블이 4천만 행 넘어가니까 인덱스 스캔도 체감 느려짐. 파티셔닝 고민하다 RANGE로 월별 파티션 걸어봄.
ALTER TABLE orders
PARTITION BY RANGE (TO_DAYS(created_at)) (
PARTITION p201312 VALUES LESS THAN (TO_DAYS('2014-01-01')),
PARTITION p201401 VALUES LESS THAN (TO_DAYS('2014-02-01')),
PARTITION p201402 VALUES LESS THAN (TO_DAYS('2014-03-01')),
PARTITION p201403 VALUES LESS THAN (TO_DAYS('2014-04-01')),
PARTITION pmax VALUES LESS THAN MAXVALUE
);
여기서 체크해야 할거. MySQL 5.5 파티셔닝은 PK / UK 에 파티션 키가 포함돼 있어야 함. orders의 PK가 id 하나면 파티션 불가능. PK를 (id, created_at) 로 composite로 바꿔야 되는데, 이러면 FK 건 다른 테이블에서 꼬임ㅠ
우리는 다행히 FK를 DB 제약으로 안 걸고 애플리케이션 레벨에서만 관리해서 composite PK로 돌릴 수 있었음.
파티션 프루닝 확인은 EXPLAIN PARTITIONS 로.
EXPLAIN PARTITIONS SELECT * FROM orders WHERE created_at BETWEEN '2014-02-01' AND '2014-02-28'; -- partitions: p201402
WHERE에 created_at 없으면 전 파티션 다 뒤짐. 그래서 어플에서 조회할때 created_at 범위 같이 넣도록 ORM 쪽 래퍼를 바꿨음.
LIST 파티션은 country_code 같은 enum값으로 쪼갤 때 유용한데 우리는 거의 안 씀. 월별 RANGE가 관리 편함. 새달되면 ADD PARTITION, 오래된건 DROP PARTITION으로 초고속 삭제. DELETE랑 비교 안될정도로 빠르다.