一、分区的优点
- 和单个磁盘或文件系统分区相比,可以存储更多的数据。
优化查询。
- where 子句中包含分区条件时,可以只扫描必要的分区。
- 涉及聚合函数的查询时,可以容易的在每个分区上并行处理,最终只需汇总得到结果。
- 对于已经过期或者不需要保存的数据,可以通过删除与这些数据有关的分区来快速删除数据。
- 跨多个磁盘来分散数据查询,以获得更大的查询吞吐量。
二、分区方法
将某张表的数据,分别存储到不同的区域中。每个分区都是独立的表,都要存储该分区数据的数据、索引等信息。
使用mysql的分区功能,可以把一个大的数据表分成多个小份,用户不需要区分不同的表名。
表中有主键的时候,分区只能使用主键
1. KEY 分区,按照某个字段取余
create table post (
id int unsigned not null AUTO_INCREMENT,
title varchar(255),
PRIMARY KEY (id)
) engine = innodb
partition by key (id) partitions 5;
2. HASH 分区,基于给定的分区个数,把数据分配到不同的分区。
create table student_hash(
id int unsigned not null auto_increment,
birthday date,
PRIMARY KEY(id,birthday);
) engine=myisam
partition by hash (month(birthday)) patitions 12;
key 和 hash 分区方法可以有效的分散热点数据。
3. RANGE 分区,基于一个给定连续区间范围,把数据分配到不同的分区
create table goods (
id int,
uname char(10)
)engine myisam
partition by range(id) (
partition p1 values less than (10),
partition p2 values less than (20),
partition p3 values less than MAXVALUE
);
4.LIST 分区,类似 RANGE 分区,区别在 LIST 分区是基于枚举出的值列表分区,RANGE 是局域给定的连续区间范围分区。
create table user (
uid int,
pid int,
uname
)engine myisam
partition by list(pid) (
partition bj values in (1),
partition ah values in (2),
partition xb values in (4,5,6)
);
# 如果试图插入的列值不包含分区值列表中时,那么 insert 操作会失败并报错,要重点注意的是,list 分区不存在类似 values less than maxvalue 这样包含其他值在内的定义方式,将要匹配的任何值都必须在值列表中找得到。
5. Clumns 分区
是在mysql5.5引入的分区类型,解决了之前版本 range 和 list 分区只支持整数分区,从而导致需要额外的函数计算得到整数或通过额外的转换表来转换为整数再分区的问题。
Columns 分区可以细分为 range columns 分区和 list columns 分区,这两种分区都支持整数,日期和字符串三大数据类型。
columns 分区的另一个亮点是支持多列分区:
mysql> create table rc3(
a int,
b int
)
partition by range columns(a,b)(
partition p01 values less than (0,10),
partition p02 values less than (10,10),
partition p03 values less than (10,20),
partition p04 values less than (10,35),
partition p05 values less than (10,maxvalue),
partition p06 values less than (maxvalue,maxvalue)
);
6. 子分区
子分区(subpartitioning)是分区表中对每个分区的再次分割,又被称为符合分区(composite partitioning)。mysql 从 mysql 5.1 开始支持对已经通过 range 或者 list 分区了的表再进行子分区,子分区既可以使用 hash 分区,也可以使用 key 分区。
mysql> create table ts (id int, purchased date)
partition by range(year(purchased))
subpartition by hash (to_days(purchased))
subpartitions 2
(
partition p0 values less than (1990),
partition p1 values less than (2000),
partition p2 values less than maxvalue,
);
表 ts 有3个 range 分区,这 3 个分区中的每个分区又进一步分成 2 个子分区,实际上,整个表被分成了 3*2=6 个分区,由于 partition by range 子句的作用,第一和第二个分区只保存 purchased 列中值小于 1990 的记录。
复合分区适用于保存非常大量的数据记录。
三、分区管理
1. 取余算法 key hash
采用取余算法的分区数量的修改,不会导致已有分区数据的丢失,需要重新分配数据到新的分区
增加分区: add partition N;
减少分区:coalesce partition N;
2. 条件算法 list range
添加分区
alert table goods add partition(
partition p4 values less than 40);
删除分区
alert table goods drop partition p1;
注意:删除条件算法的分区,会导致分区数据的丢失
四、mysql 分区处理 null 值的方式
mysql 不禁止在分区键值上使用 null , 分区键可能是一个字段或者一个用户定义的额表达式。一般情况下,mysql 的分区把 null 当作零值,或者一个最小值进行处理。
range 分区中,null 值会被当作最小值来处理;
list 分区中,null 值必须出现在枚举列表中,否则不被接受;
hash/key 分区中,null 值会被当作零值来处理。