通过show variables like '%datadir%';命令查看mysql的data存放目录,进入所在的数据库目录(如test)
打开目录,里面包含不同文件格式的引擎数据库
myisam
.frm : 存储表结构
.MYD : 存储表数据
.MYI : 存储索引文件
innodb: 只有设置成独立表空间才能做成功表分区
.frm : 表结构
.ibd : 数据 + 索引
range分区
给定一个连续区间的范围值进行分区,某个字段的值满足这个范围就会被分配到该分区。适用于字段的值是连续的区间的字段,如 日期范围, 连续的数字,必须为升序
create table a_range (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) DEFAULT NULL,
`age` date NOT NULL ,
PRIMARY KEY (`id`,age)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1
partition by range (YEAR(age)) (
partition 70hou values less than (1980),
partition 80hou values less than (1990),
partition 90hou values less than (2000),
partition 00hou values less than maxvalue
);
分区字段:分区字段必须是主键,表示要按照哪个字段进行分区,可以是一个字段名,也可以是对某个字段进行表达式运算如year(create_time),使用range最终的值必须是数字
分区名称: 要保证不同,也可以采用 p0、p1、p2 这样的分区名称,
less than : 表示小于
Value : 表示要小于某个具体的值,如 less than (10) 那么分区字段的值小于10的都会被分到这个分区
maxvalue: 表示一个最大的值
运行结果:
查看分区数据存储于哪个区
select
partition_name,
partition_expression,
partition_description,
table_rows
from information_schema.partitions
where table_schema = schema() and table_name = 'a_range';
list 分区
create table a_list (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) DEFAULT NULL,
`shopId` int NOT NULL ,
PRIMARY KEY (`id`,shopId)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1
partition by list (shopId) (
partition east values in (1,3,5),
partition south values in (2,4,6),
partition west values in (7,8,9),
partition north values in (10,11)
);
columns分区
create table a_column (
a int(11) NOT NULL AUTO_INCREMENT,
b int(11) NOT NULL ,
PRIMARY key (a,b)
)ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1
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)
);
range columns分区键的比较(元组的比较)其实就是多列排序,先根据a字段排序再根据b字段排序,根据排序结果来分区存放数据,和range单字段的分区排序的规则实际上是一样的
hash分区
mysql支持两种hash分区,
1.常规hash分区和线性hash分区(linear hash分区),常规hash分区使用的是取模算法,对应一个表达式expr是可以计算出它被保存到哪个分区中,N = MOD(expr, num)
2.线性hash分区使用的是一个线性的2的幂运算法则。
create table a_hash (
`id` int(11) NOT NULL,
`username` varchar(255) DEFAULT NULL,
`shopId` int NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8
PARTITION BY HASH(shopId) PARTITIONS 2;
基于shopId分成两个区
key分区
create table a_key (
`id` int(11) NOT NULL,
`username` varchar(255) DEFAULT NULL,
`shopId` int NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8
PARTITION BY KEY(shopId) PARTITIONS 2;
子分区
-- 根据年进行分区
-- 再根据天数分区
-- 3个range分区(p0,p1,p2)又被进一步分成2个子分区,实际上整个分区被分成了 3 x 2 = 6个分区
create table a_subpart (
id int,
birthday date
)
partition by range(year(birthday))
subpartition by hash(to_days(birthday)) subpartitions 2
(
partition p0 values less than (1990)(SUBPARTITION s0, SUBPARTITION s1),
partition p1 values less than (2000)(SUBPARTITION s2, SUBPARTITION s3),
partition p2 values less than maxvalue(SUBPARTITION s4, SUBPARTITION s5)
);
管理分区
-- 删除list或者range分区(同时删除分区对应的数据)
alter table <table> drop partition <分区名称>;
-- 新增分区
-- range添加新分区
alter table <table> add partition(partition p4 values less than MAXVALUE);
-- list添加新分区
alter table <table> add partition(partition p4 values in (25,26,28));
-- hash, key重新分区
alter table <table> add partition partitions 4;
-- 子分区添加新分区,虽然我没有指定子分区,但是系统会给子分区命名的
alter table <table> add partition(partition p3 values less than MAXVALUE);
-- range重新分区
ALTER TABLE user REORGANIZE PARTITION
p0,p1,p2,p3,p4 INTO
(PARTITION p0 VALUES LESS THAN MAXVALUE);
-- list重新分区
ALTER TABLE < TABLE > REORGANIZE PARTITION
p0,p1,p2,p3,p4 INTO
( PARTITION p0 VALUES IN ( 1, 2, 3, 4, 5 ));