什么是Mysql表分区
将一个表或者索引分解为多个更小、更可管理的部分。
从逻辑上将,只有一个表或者索引,但是在物理上这个表或索引可能由数十个物理分区组成。
每个分区都是独立的对象,可以独自处理,也可以作为一个更大对象的一部分进行处理。
表分区的优点
1) 分区表对业务透明,只需要维护一个表的数据结构
2) 冷热分离:表非常大且只在表的最后部分有热点数据,冷数据根据分区规则自动归档。
3) 定期淘汰历史数据:按时间写入,历史数据可淘汰,可快速删除,空间可快速回收。
- 可通过TRUNCATE操作快速清理特定分区数据
4) 优化查询:在where字句中包含分区列时,分区可以大大提高查询效率,减少缓存开销、减少IO开销。
5) 统计性能提升:在涉及sum()和count()这类聚合函数的查询时,可以在每个分区上面并行处理,最终只需要汇总所有分区得到的结果
表分区的缺点
1) 表分区的数量有限(mysql5.6之后支持8192个分区,之前最多1024个分区)
2) 如果分区字段中有主键或者唯一索引列,那么所有主键列和唯一索引列都必须包含进来,如果表中有主键或唯一索引,那么分区键必须是主键或唯一索引
3) 分区表中无法使用外键约束
4) mysql数据库支持的分区类型为水平分区,并不支持垂直分区
5) DDL操作需要锁定所有分区,导致所有分区上操作都被阻塞
表分区的规则
RANGE分区
RANGE分区特点
1)根据分区键值的范围把数据行存储到表的不同分区中
2)多个分区的范围要连续,但是不能重叠
3)默认情况下使用VALUES LESS THAN属性,即每个分区不包括指定的那个值
RANGE分区的适用场景
1)分区键为日期或是时间类型
2)所有查询中都包括分区键(避免跨分区查询)
3)定期按分区范围清理历史数据
alter table t_range drop partition p2018;
CREATE TABLE `t_range` (
id int(11),
created_at datetime
) ENGINE=InnoDB DEFAULT CHARSET=utf8
partition by range(year(created_at))(
partition p2017 values less than (2018),
partition p2018 values less than (2019),
partition p2019 values less than (2020),
partition p2020 values less than (2021)
);
ALTER TABLE t_range reorganize partition p2019 into (
PARTITION p2017 VALUES LESS THAN (2018),
PARTITION p2018 VALUES LESS THAN (2019),
PARTITION p2019 VALUES LESS THAN (2020)
);
ALTER TABLE t_range reorganize partition p2020 into (
PARTITION p2020 VALUES LESS THAN (2021),
PARTITION p2021 VALUES LESS THAN (2022)
)
LIST分区
LIST分区的特点
1)按分区键取值的列表进行分区
2)同范围分区一样,各分区的列表值不能重复
3)每一行数据必须能找到对应的分区列表,否则数据插入失败
CREATE TABLE `t_list` (
id int(11),
age int(11)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
partition by list (b) (
partition p0 values in (1,3,5,7,9),
partition p1 values in (2,4,6,8,0)
);
alter table t_list add partition(partition p1 values in(0));
HASH分区
HASH分区的特点:
1)根据MOD(分区键,分区数)的值把数据行存储到表的不同分区中
2)数据可以平均的分布在各个分区中
3)HASH分区的键值必须是一个INT类型的值,或是通过函数可以转为INT类型
CREATE TABLE `t_hash` (
id bigint(20),
uuid VARCHAR(64)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
partition by hash (id) partitions 4;
KEY分区
key分区和hash分区相似,不同在于hash分区是用户自定义函数进行分区,key分区使用mysql数据库提供的函数进行分区。
注意:
如果设置40,64,128等偶数个分区数(PARTITIONS 64),会导致编号为奇数的分区(p1, p3, p5, p7, ... p2n-1)完全插不进数据;
如果设置63,121(PARTITIONS 63)这种奇数但非质数个分区数,所有分区都会有数据,但是不均匀;
如果设置137,31这种质数个分区数(PARTITIONS 137),所有分区都会有数据,并且非常均匀;
CREATE TABLE `t_key` (
uuid VARCHAR(64)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
partition by KEY(uuid) partitions 7;
合理选择分区键
1)优先主键
2)以空间换时间
3)定义分区数量