分區是 MySQL 將大表在物理層面拆分為多個獨立片段的機制,能顯著提升大數據量下的查詢效能、維護效率與存儲彈性。本文涵蓋支援檢測、分區類型原理、建表語法、裁剪原理、維護操作、效能邊界與避坑指南,構建分區表技術全景圖。
-- 方法 1:查看變數 (最快)
SHOW VARIABLES LIKE '%partition%';
-- 輸出 have_partitioning = YES 表示支援
-- 方法 2:查看插件狀態
SHOW PLUGINS;
-- 輸出 partition | ACTIVE | STORAGE ENGINE | GPL 表示已啟用
-- 方法 3:INFORMATION_SCHEMA
SELECT * FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME='partition';
注意:MySQL 5.1+ 官方版預設編譯支援分區;Percona Server、MariaDB 同樣支援;極少數精簡編譯版可能移除。
| 維度 | 水平分區 (Horizontal Partitioning / MySQL Partitioning) | 垂直分區 (Vertical Partitioning / 手動拆表) |
|---|---|---|
| 定義 | 按行切分:同一表結構,不同行存入不同分區 | 按列切分:將寬表拆分為多張窄表 (主鍵關聯) |
| MySQL 原生支援 | 是 (PARTITION BY ...) | 否 (需應用層/中間件實現) |
| 表結構 | 單一邏輯表,多物理分區文件 | 多張獨立物理表 |
| 索引 | 全局索引 (每分區獨立 B+ 樹) | 各表獨立索引 |
| 適用場景 | 時間序列、範圍查詢、歸檔清理、大表維護 | 寬表優化、熱冷列分離、Blob/Text 隔離 |
| 透明度 | 對應用透明 (SQL 無感) | 應用需感知多表、或中間件路由 |
CREATE TABLE sales (
id INT NOT NULL,
sale_date DATE NOT NULL,
amount DECIMAL(10,2),
PRIMARY KEY (id, sale_date) -- 分區鍵必須包含在主鍵/唯一鍵中
)
PARTITION BY RANGE (YEAR(sale_date)) (
PARTITION p2020 VALUES LESS THAN (2021),
PARTITION p2021 VALUES LESS THAN (2022),
PARTITION p2022 VALUES LESS THAN (2023),
PARTITION p2023 VALUES LESS THAN (2024),
PARTITION p_future VALUES LESS THAN MAXVALUE
);
WHERE sale_date >= '2023-01-01' → 僅掃描 p2023、p_futureCREATE TABLE users (
id INT NOT NULL,
region_code CHAR(2) NOT NULL,
name VARCHAR(50),
PRIMARY KEY (id, region_code)
)
PARTITION BY LIST COLUMNS(region_code) (
PARTITION p_east VALUES IN ('BJ','SH','TJ','HE','LN','JS','ZJ','SD'),
PARTITION p_south VALUES IN ('GD','GX','HI','FJ','YN','CQ','SC','GZ'),
PARTITION p_west VALUES IN ('SN','GS','QH','NX','XJ','SC','XZ'),
PARTITION p_central VALUES IN ('HA','HB','HN','JX','SX','AH','JL','HL')
);
-- HASH: 用戶自定義運算式
CREATE TABLE logs (
id INT NOT NULL,
created_at DATETIME NOT NULL,
msg TEXT,
PRIMARY KEY (id, created_at)
)
PARTITION BY HASH(MONTH(created_at))
PARTITIONS 12; -- 自動建立 12 個分區
-- KEY: MySQL 內部哈希函數 (支援非整數欄位)
PARTITION BY KEY(created_at)
PARTITIONS 12;
=/IN 等值查詢裁剪,範圍查詢全分區掃描PARTITION BY RANGE (YEAR(sale_date))
SUBPARTITION BY HASH (MONTH(sale_date))
SUBPARTITIONS 3 (
PARTITION p2023 VALUES LESS THAN (2024),
PARTITION p2024 VALUES LESS THAN (2025)
);
-- 每年分區下再按月哈希為 3 個子分區,共 2*3=6 物理段
YEAR()、TO_DAYS()、TO_SECONDS()、UNIX_TIMESTAMP() 等單調函數 (5.7+ 擴展)| 操作 | 語法 | 典型場景 | 鎖影響 |
|---|---|---|---|
| 新增分區 | ALTER TABLE t ADD PARTITION (PARTITION p2024 VALUES LESS THAN (2025)); | 時間推進、預建未來分區 | 元數據鎖,極快 |
| 刪除分區 (數據同刪) | ALTER TABLE t DROP PARTITION p2020; | 歷史數據歸檔清理 (秒級) | 元數據鎖,極快 |
| 截斷分區 (保留結構) | ALTER TABLE t TRUNCATE PARTITION p2020; | 清空分區數據,保留分區定義 | 元數據鎖,極快 |
| 重組分區 (合併/拆分) | ALTER TABLE t REORGANIZE PARTITION p2023,p2024 INTO (PARTITION p2023 VALUES LESS THAN (2024), PARTITION p2024 VALUES LESS THAN (2025)); | 調整分區邊界 | **重建數據,排他鎖,大表慎用** |
| 交換分區 (與非分區表) | ALTER TABLE t EXCHANGE PARTITION p2020 WITH TABLE t_archive; | 歸檔導出、歷史數據載入 | 元數據鎖,極快 |
| 分區裁剪驗證 | EXPLAIN PARTITIONS SELECT * FROM t WHERE sale_date='2023-06-01'; | 查看 partitions 欄位確認僅掃描目標分區 | 無 |
DROP PARTITION 秒級清理億級歷史數據,無 DELETE 產生碎片、鎖表、Binlog 膨脹ANALYZE TABLE 更新各分區統計| 方案 | 實現層 | 透明度 | 擴展性 | 維護複雜度 | 適用規模 |
|---|---|---|---|---|---|
| MySQL Partition | Server 內核 | 完全透明 | 單機物理限制 | 低 | 單表 5000萬~5億行 |
| 應用層分表 | 應用/中間件 | 感知路由 | 跨機器水平擴展 | 高 | 單表 > 5億行、寫入 > 1萬 QPS |
| 分庫分表 (Sharding) | 中間件/Proxy | 感知路由 | 線性擴展 | 極高 | TB 級、萬級 QPS、多租戶隔離 |
MySQL 原生分區是單機大表優化的「銀彈」,但非萬能鑰匙。**「大表、明顯劃分特徵、固定查詢模式、定期歸檔」**是其核心適用邊界。在微服務、雲原生架構下,分區常作為分庫分表前的過渡方案,或配合分庫分表作為單分片內部優化手段。掌握分區裁剪驗證 (EXPLAIN PARTITIONS)、維護操作原子性 (DROP/EXCHANGE PARTITION)、存儲分級掛載,能最大化釋放分區價值。