MySQL 5.1 引入分區表,將大表按規則拆分為物理獨立的分區,實現數據劃歸、歷史清理、跨磁盤 I/O 分攤。本文系統講解分區原理、四大類型、管理操作、實測對比及生產避坑指南。
| 類型 | 適用場景 | 分區函數示例 |
| RANGE | 時間序列、連續數值區間 | PARTITION BY RANGE (TO_DAYS(date_col)) |
| LIST | 離散值枚舉(地區、狀態碼) | PARTITION BY LIST (region_id) |
| HASH | 均勻分佈、無明顯業務邊界 | PARTITION BY HASH (id) |
| KEY | 類似 HASH,但由 MySQL 內部哈希函數計算 | PARTITION BY KEY (col) |
子分區: 分區內再劃分,每個分區子分區數量必須一致;若顯式定義一個分區的子分區,必須定義所有分區的子分區。
分區管理 DDL
RANGE / LIST
-- 刪除分區(數據同步刪除,極快)
ALTER TABLE t DROP PARTITION p20110809;
-- 新增分區(只能加在高端,範圍需連續)
ALTER TABLE t ADD PARTITION (PARTITION p20110819 VALUES LESS THAN (734734));
-- 合並/拆分重組(僅相鄰分區)
ALTER TABLE t REORGANIZE PARTITION p0,p1 INTO (
PARTITION p0 VALUES LESS THAN (100),
PARTITION p1 VALUES LESS THAN (200)
);
HASH / KEY
-- 增加分區數
ALTER TABLE t ADD PARTITION PARTITIONS 4;
-- 合並分區(COALESCE,非 DROP)
ALTER TABLE t COALESCE PARTITION 2;
查看分區信息
SELECT * FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_SCHEMA = SCHEMA() AND TABLE_NAME = 't';
實測對比:1708 萬行 InnoDB 表(RANGE 按天分區 vs 不分區)
| 查詢場景 | 分區表 | 普通表 | 分析 |
| 全表 COUNT(*) | 21.62s | 29.20s | 分區並行掃描略快 |
| 分區鍵範圍(RECORD_DATE) | 1.85s | 3.10s | 分區剪枝生效,掃描行數 376萬 vs 854萬 |
| 非分區鍵範圍(RECORD_DATETIME) | 2.83s | 5.60s | 優化器推斷時間映射分區,仍有剪枝效果 |
| 非分區鍵點查(ALERT_TYPE=1) | 8.49s | 12.88s | 全分區掃描,但並行度較高 |
| 刪除整天數據(DROP PARTITION) | 0.65s | 89.68s (DELETE) | 元數據操作 vs 全表掃描刪除,碾壓級優勢 |
| 跨分區刪除(ALERT_TYPE=1) | 55.20s | 50.26s | 分區表略慢(需合並多個分區變更) |
EXPLAIN PARTITIONS 關鍵指標
partitions 列顯示實際掃描的分區列表;NULL 表示全表掃描。
rows 估算掃描行數,分區剪枝生效時大幅下降。
生產避坑指南
- MySQL 5.1 分區尚不成熟: 5.1.22 仍缺分區級
OPTIMIZE/REPAIR/CHECK,空間回收需整表操作。
- 唯一索引限制: 主鍵/唯一鍵必須包含分區列,否則報錯。
- RANGE 新增分區只能追加高端,不可插入中間。
- REORGANIZE 僅相鄰分區,不可跨越,不可改變分區類型/表達式。
- HASH/KEY 分區實際業務價值有限,建議優先 RANGE/LIST。
最佳實踐場景
- 日誌/監控/統計類大表,按天/月 RANGE 分區,定期
DROP PARTITION 清理歷史。
- 查詢高頻帶分區鍵條件(時間範圍),充分利用分區剪枝。
- 寫入為主、修改少、需跨磁盤分佈存儲降低單盤 I/O 壓力。
- 上一篇文章: MySQL server has gone away 兩大根因與解決方案:wait_timeout 與連接存活檢測
- 下一篇文章: Delphi + dbExpress + MySQL 多層更新「Record not found」錯誤根因與修復
Copyright ©
程式碼之家 All Rights Reserved