MySQL 分区(Partitioning)概述
分区(Partitioning) 是 MySQL 将一张大表拆分成多个更小的物理存储单元(称为“分区”)的技术,它能提升查询性能,优化存储管理,适用于 大数据量的表。
分区本质上是 一种物理存储优化方式,逻辑上仍然是 一张表,但数据在底层被分散存储到不同的分区中。
1. 为什么要使用分区?
(1) 提高查询性能
- 范围查询更快:如果查询的条件只涉及某个分区,MySQL 只需扫描该分区,而不需要全表扫描。
- 并行查询优化:某些存储引擎(如 InnoDB)可以并行访问多个分区,加速查询。
(2) 提高数据管理灵活性
- 历史数据管理更方便:可以将不同时间段的数据存放在不同分区,比如 按年月分区存储订单数据,便于定期清理老数据。
- 删除分区比 DELETE 更高效:可以直接
DROP PARTITION
,而不是DELETE
大量行,提高效率。
(3) 适合大数据存储
- 单表行数太多会影响性能:分区后,每个分区存储更少的数据,索引变小,查询更高效。
2. MySQL 分区的类型
MySQL 主要支持以下 5 种分区方法:
分区类型 | 说明 | 适用场景 |
---|---|---|
RANGE 分区 | 按照范围划分数据 | 按时间、年龄等范围存储 |
LIST 分区 | 按指定的值存储数据 | 按地区、分类等存储 |
HASH 分区 | 通过哈希函数分配数据 | 负载均衡、大数据存储 |
KEY 分区 | 类似于 HASH,使用 MySQL 内部哈希函数 | 适用于分布式存储 |
SUBPARTITION(子分区) | 在主分区下再划分子分区 | 复杂存储场景 |
3. 分区的具体实现
(1) RANGE 分区(范围分区)
示例:按年份分区存储订单数据
CREATE TABLE orders (
id INT NOT NULL,
order_date DATE NOT NULL,
total_amount DECIMAL(10,2),
PRIMARY KEY (id, order_date)
)
PARTITION BY RANGE (YEAR(order_date)) (
PARTITION p2019 VALUES LESS THAN (2020),
PARTITION p2020 VALUES LESS THAN (2021),
PARTITION p2021 VALUES LESS THAN (2022),
PARTITION pmax VALUES LESS THAN MAXVALUE
);
特点:
order_date
用于分区。- 2019 年的数据存
p2019
,2020 年存p2020
,以此类推。 pmax
作为默认分区,存储所有不符合其他条件的数据。
✅ 适用于:
- 按时间查询数据,比如
SELECT * FROM orders WHERE order_date BETWEEN '2020-01-01' AND '2020-12-31'
,只需扫描p2020
分区,提高查询效率。
(2) LIST 分区(列表分区)
示例:按地区分区存储用户数据
CREATE TABLE users (
id INT NOT NULL,
name VARCHAR(50),
region_id INT NOT NULL,
PRIMARY KEY (id, region_id)
)
PARTITION BY LIST (region_id) (
PARTITION p_north VALUES IN (1,2,3),
PARTITION p_south VALUES IN (4,5,6),
PARTITION p_other VALUES IN (7,8,9,10)
);
特点:
region_id
用于分区。p_north
存region_id
为1,2,3
的用户,p_south
存4,5,6
,p_other
存7,8,9,10
。
✅ 适用于:
- 按分类存储,如按地区、业务类型等划分数据。
(3) HASH 分区(哈希分区)
示例:订单数据按 id
进行哈希分区
CREATE TABLE orders (
id INT NOT NULL,
order_date DATE NOT NULL,
PRIMARY KEY (id, order_date)
)
PARTITION BY HASH(id) PARTITIONS 4;
特点:
id
经过HASH(id) % 4
运算,分配到4
个分区之一。- 均衡存储数据,防止热点问题。
✅ 适用于:
- 大规模数据存储,如用户 ID、订单 ID 分布式存储,能均匀分布数据,防止查询热点。
(4) KEY 分区(类似 HASH,但使用 MySQL 内置哈希算法)
CREATE TABLE employees (
id INT NOT NULL,
name VARCHAR(50),
department_id INT NOT NULL,
PRIMARY KEY (id, department_id)
)
PARTITION BY KEY(id) PARTITIONS 3;
特点:
id
通过 MySQL 内部哈希函数计算分区。- 适用于无特定哈希算法需求的情况。
(5) 组合分区(子分区 Subpartitioning)
示例:订单表按年份 RANGE 分区,再按 ID 进行 HASH 分区
CREATE TABLE orders (
id INT NOT NULL,
order_date DATE NOT NULL,
PRIMARY KEY (id, order_date)
)
PARTITION BY RANGE (YEAR(order_date))
SUBPARTITION BY HASH(id)
SUBPARTITIONS 4 (
PARTITION p2019 VALUES LESS THAN (2020),
PARTITION p2020 VALUES LESS THAN (2021),
PARTITION p2021 VALUES LESS THAN (2022)
);
特点:
- 先按
YEAR(order_date)
分区(RANGE)。 - 再按
id
进行 HASH 分区,保证数据均衡存储。
✅ 适用于:
- 数据量极大且查询条件复杂的场景。
4. 分区的缺点
- 索引受限:主键必须包含分区键,无法跨分区索引查询。
- 分区管理复杂:需要手动管理数据的划分。
- 数据量小的表不适合:小表分区反而降低性能,增加维护成本。
5. 分区 VS 分库分表
对比项 | 分区 | 分库分表 |
---|---|---|
适用场景 | 大表优化 | 超大表、分布式架构 |
实现方式 | MySQL 内部处理 | 需要应用程序或中间件 |
查询优化 | 只扫描相关分区 | 需要路由查询 |
管理复杂度 | 低 | 高 |
索引支持 | 受限 | 更灵活 |
✅ 小型单机数据库适合分区,大规模分布式数据库适合分库分表。
6. 总结
- MySQL 分区是一种物理存储优化技术,适用于 大表,能提高查询性能和数据管理效率。
- 常见分区类型:RANGE(范围)、LIST(列表)、HASH(哈希)、KEY(MySQL 内部哈希)、子分区(组合)。
- 分区适合 大数据量表,特别是按时间、类别存储的数据,但索引受限,不适合小表。
如果数据量巨大,查询有明显的时间或类别特征,分区是一个不错的选择! 🚀