MySQL 表分区
MySQL表分区是将一个大表分割成若干个小表的技术。这样做可以提高查询和维护的效率,并且还可以改善数据的管理方式。
注意:如果分区字段中有主键或者唯一索引的列,那么所有主键列和唯一索引列都必须包含进来(即分区的字段也必须是主键或者唯一索引)
分区适用场景
- 大型表处理
- 时间范围查询
- 数据归档和数据保留
- 并行查询和负载均衡
- 数据删除和维护
判断当前MySQL是否支持分区?
1
|
show variables like '%partition%';
|
以下是几种常见的分区类型:
-
RANGE分区:基于给定的一个给定列的值,将数据划分到不同的分区。
-
LIST分区:类似于RANGE分区,但是列值是离散的集合。
-
HASH分区:基于用户定义的表达式的返回值进行分区,该表达式对分区的数量进行哈希。
-
KEY分区:类似于HASH分区,但是使用的哈希函数是由MySQL服务器提供的。
-
COLUMNS分区:基于列值的范围或列表来进行分区,适用于某些特定的数据类型。
RANGE分区
以下是一个RANGE分区的示例:
假设有一个orders表,包含一个order_date字段,可以根据order_date字段的值将表分为几个分区:
1
2
3
4
5
6
7
8
9
10
11
12
|
CREATE TABLE orders (
order_id INT NOT NULL,
order_date DATE NOT NULL,
order_amount DECIMAL(10, 2) NOT NULL
)
PARTITION BY RANGE (YEAR(order_date)) (
PARTITION p0 VALUES LESS THAN (2023),
PARTITION p1 VALUES LESS THAN (2024),
PARTITION p2 VALUES LESS THAN (2025),
PARTITION p3 VALUES LESS THAN (2026),
PARTITION pmax VALUES LESS THAN MAXVALUE
);
|
创建了一个按年份划分的orders表,将订单按照它们的年份放入不同的分区。p0分区包含order_date在2023年以前的所有订单,p1分区包含2024年,以此类推。pmax分区包含所有2026年以后的订单。
LIST分区
LIST 分区是根据某一列的离散值将数据分布到不同的分区。
示例:
1
2
3
4
5
6
7
8
9
10
|
CREATE TABLE users (
id INT,
username VARCHAR(50),
region VARCHAR(50)
)
PARTITION BY LIST (region) (
PARTITION p_east VALUES IN ('New York', 'Boston'),
PARTITION p_west VALUES IN ('Los Angeles', 'San Francisco'),
PARTITION p_other VALUES IN (DEFAULT)
);
|
HASH分区
HASH 分区是使用哈希算法将数据均匀地分布到多个分区中。
示例:
1
2
3
4
5
6
|
CREATE TABLE users (
id INT,
username VARCHAR(50),
region VARCHAR(50)
)
PARTITION BY HASH (id) PARTITIONS 4;
|
PARTITIONS 4 指定4个分区
KEY分区
KEY 分区是根据某一列的哈希值将数据分布到不同的分区。和HASH分区不同在于使用的哈希算法不同。
示例:
1
2
3
4
5
6
|
CREATE TABLE users (
id INT,
username VARCHAR(50),
region VARCHAR(50)
)
PARTITION BY KEY (id) PARTITIONS 4;
|
PARTITIONS 4 指定4个分区
COLUMNS 分区
包括 RANGE COLUMNS 分区和 LIST COLUMNS 分区
RANGE COLUMNS 分区是根据列的范围值将数据分布到不同的分区的分区策略。
1
2
3
4
5
6
7
8
9
10
11
12
|
CREATE TABLE users (
id INT,
username VARCHAR(50),
region VARCHAR(50),
birthday DATE NOT NULL
)
PARTITION BY LIST COLUMNS (region, YEAR(category)) (
PARTITION p_east VALUES LESS THAN (('New York', 2022), ('Boston', 2022)),
PARTITION p_west VALUES LESS THAN (('Los Angeles', 2022), ('San Francisco', 2022)),
PARTITION p_east_other VALUES LESS THAN (('New York', MAXVALUE)),
PARTITION p_west_other VALUES LESS THAN (('Los Angeles', MAXVALUE))
);
|
LIST COLUMNS 分区是根据列的离散值将数据分布到不同的分区的分区策略。
1
2
3
4
5
6
7
8
9
10
11
|
CREATE TABLE users (
id INT,
username VARCHAR(50),
region VARCHAR(50),
category VARCHAR(50)
)
PARTITION BY LIST COLUMNS (region, category) (
PARTITION p_east VALUES IN (('New York', 'A'), ('Boston', 'B')),
PARTITION p_west VALUES IN (('Los Angeles', 'C'), ('San Francisco', 'D')),
PARTITION p_other VALUES IN (DEFAULT)
);
|
添加分区
1
2
|
alter table table_name add partition (partition new_part values less than (4000)); -- range 分区
alter table table_name add partition (partition new_part values in (40)); -- lists分区
|
删除分区
1
|
alter table table_name drop partition part_name;
|
drop方式删除会删除分区数据
1
|
alter table table_name remove partitioning;
|
remove不会删除数据
重新分区
range分区
1
2
3
4
|
alter table table_name partition by range(id)(
partition p1 values less than (2000),
partition p2 values less than (4000)
);
|
hash分区
1
|
alter table table_name partition by hash(id) partitions 7;
|
合并分区
合并相邻两个分区
1
|
ALTER TABLE table_name COALESCE PARTITION p1, p2;
|
合并两个分区
1
|
alter table table_name reorganize partition p1,p3 into (partition p1 values less than (1000));
|
重组分区
1
2
3
4
5
|
alter table table_name
reorganize partition p1 into(
partition p1 values less than (100),
partition p3 values less than (1000)
);
|
查询分区分析
1
|
explain partitions select ...
|
分区统计信息
1
|
ALTER TABLE users ANALYZE PARTITION p1;
|
参考