===================================
原文链接:
https://blog.csdn.net/weixin_39860583/article/details/113438389
====
分区
先复习一下Myisam和InnoDB这两种引擎的文件存储格式:
Myisam:
frm 存表结构的文件
MYD 存表数据的文件
MYI 存索引的文件
Innodb:
frm 存表结构的文件
ibd 存表数据的文件
Innodb又分为两种:共享表空间和独享表空间
从mysql 5.6.6版本开始,独立表空间(file-per-table tablespaces)默认是开启的(也就是innodb_file_per_table参数不设置时,它默认等于1),而mysql5.5以前默认设置是共享表空间,使用表分区功能前先要检查
innodb_file_per_table是否开启。
共享表空间就是一个库的所有表都放在一个文件中,如ibddata1这个文件就是共享表空间。
独享表空间就是一个表单独放在一个文件中。
很明显,独享表空间的性能更高。
show variables like “%innodb_file_per_table%”;
这个参数为ON表示使用独享表空间。
分表的情况是
tb_1 对应 文件1(包含结构文件和数据文件)
tb_2 对应 文件2(包含结构文件和数据文件)
tb_3 对应 文件3(包含结构文件和数据文件)
数据插入哪个表或者数据查询从哪个表查,我们要在业务层自己写算法来判断
分区的情况是(假如分区为3个区)
文件1
tb 对应 文件2
文件3
分成几个区,就会生成几个文件,但是表还是1个表。
而算法和策略不需要再业务层自己实现,而是mysql内部实现。
常见分区的策略有4种:
Range:如id为1100的数据存放到第一个分区,101200放到第二个分区,…依次类推(以连续型数据字段作为分区的字段)
List:如分类A的数据放到第一个分区,B分类的数据放第二个分区,…以此类推(以离散型数据字段作为分区字段)
Hash:使用表达式作为分区标准, 如对字段取模,将模相同的数据放到相同分区
Key:和Hash类似,可以对某字段使用表达式作为分区标准。这个和Hash本质还是一样的。
重点是前3个。
PS:建立分区的字段必须是主键字段或者被包含在主键字段(如复合主键)中。例子如下:
在test库先建立一个普通的表:
create table t_base(id int primary key auto_increment,name varchar(10))engine=innodb;
insert into t_base (name) values (“zbp”);
insert into t_base (name) select name from t_base; # 蠕虫复制400多万条数据。
select count(*) from t_base; # 4194304
更改他们的name字段为随机的数字
update t_base set name=ceil(rand()*5000000);
现在mysql存放数据的目录的test目录中可以看到t_baes.ibd(290M)和t_base.frm文件
创建range分区的表
create table t_range(
id int primary key auto_increment,
name varchar(10)
)engine=innodb partition by range(id)(
partition p0 values less than (1000000), # p0是分区名
partition p1 values less than (2000000),
partition p2 values less than (3000000),
partition p3 values less than (4000000),
partition p4 values less than (5000000) #可使用maxvalue关键字表示最大的id数
);
此时会出现t_range#p#p0~4.ibd这4个表数据文件和一个t_range.frm表结构文件。
将t_base数据写入t_range中
insert into t_range select * from t_base;
PS,如果删除某个分区,该分区下的数据会被删掉。
alter table t_range drop partition p4;
查看分区情况
show create table t_range;
创建List分区,List分区字段必须是int型,不能是字符串型
create table t_list(
id int auto_increment,
type_id int ,
name varchar(20),
primary key (id,type_id)
)engine=innodb partition by list(type_id)(
partition p0 values in (1,2,3),
partition p1 values in (4),
partition p2 values in (5,6)
);
往t_list中插入500万数据
insert into t_list (id,type_id,name) select id,ceil(rand()*6) type_id,name from t_base;
创建hash分区,要指定分区个数,生成的4个表数据文件是一样大的,因为hash分区方式会将数据平均分配到每个分区,其实是取模算法。
create table t_hash(
id int primary key auto_increment,
name varchar(10)
)engine=innodb partition by hash(id) partitions 4;
指定创建4个分区,对id进行4的取模
select * from t_hash limit 10; # 从第一个分区获取10条数据,第一个分区是模为0的分区,故得到的id都是4的倍数
PS 如果只想移除分区但不想删除数据可以使用
alter table xxx remove partitioning;
但会删除所有分区
作者不推荐使用分区,因为mysql 5.7版本以前的分区功能有比较大不稳定性,可能造成比较严重的性能问题。
更多关于分区的操作如合并分区,修改分区可参考网上资料
=======================================