追加 Mysql分区 资料
RANGE分区
按照RANGE分区的表是通过如下一种方式进行分区的,每个分区包含那些分区表达式的值位于一个给定的连续区间内的行
//创建range分区表
mysql> CREATE TABLE IF NOT EXISTS `user` (
-> `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
-> `name` varchar(50) NOT NULL DEFAULT '' COMMENT '名称',
-> `sex` int(1) NOT NULL DEFAULT '0' COMMENT '0为男,1为女',
-> PRIMARY KEY (`id`)
-> ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1
-> PARTITION BY RANGE (id) (
-> PARTITION p0 VALUES LESS THAN (3),
-> PARTITION p1 VALUES LESS THAN (6),
-> PARTITION p2 VALUES LESS THAN (9),
-> PARTITION p3 VALUES LESS THAN (12),
-> PARTITION p4 VALUES LESS THAN MAXVALUE
-> );
Query OK, 0 rows affected (0.13 sec)
//插入一些数据
mysql> INSERT INTO `test`.`user` (`name` ,`sex`)VALUES ('tank', '0')
-> ,('zhang',1),('ying',1),('张',1),('映',0),
-> ('test1',1),('tank2',1),('tank1',1),('test2',1),
-> ('test3',1),('test4',1),('test5',1),('tank3',1)
-> ,('tank4',1),('tank5',1),('tank6',1),('tank7',1)
-> ,('tank8',1),('tank9',1),('tank10',1),('tank11',1),
-> ('tank12',1),('tank13',1),('tank21',1),('tank42',1);
Query OK, 25 rows affected (0.05 sec)
Records: 25 Duplicates: 0 Warnings: 0
//到存放数据库表文件的地方看一下,my.cnf里面有配置,datadir后面就是
[root@BlackGhost test]# ls |grep user |xargs du -sh
4.0K user#P#p0.MYD
4.0K user#P#p0.MYI
4.0K user#P#p1.MYD
4.0K user#P#p1.MYI
4.0K user#P#p2.MYD
4.0K user#P#p2.MYI
4.0K user#P#p3.MYD
4.0K user#P#p3.MYI
4.0K user#P#p4.MYD
4.0K user#P#p4.MYI
12K user.frm
4.0K user.par
//取出数据
mysql> select count(id) as count from user;
+-------+
| count |
+-------+
| 25 |
+-------+
1 row in set (0.00 sec)
//删除第四个分区
mysql> alter table user drop partition p4;
Query OK, 0 rows affected (0.11 sec)
Records: 0 Duplicates: 0 Warnings: 0
/**存放在分区里面的数据丢失了,第四个分区里面有14条数据,剩下的3个分区
只有11条数据,但是统计出来的文件大小都是4.0K,从这儿我们可以看出分区的
最小区块是4K
*/
mysql> select count(id) as count from user;
+-------+
| count |
+-------+
| 11 |
+-------+
1 row in set (0.00 sec)
//第四个区块已删除
[root@BlackGhost test]# ls |grep user |xargs du -sh
4.0K user#P#p0.MYD
4.0K user#P#p0.MYI
4.0K user#P#p1.MYD
4.0K user#P#p1.MYI
4.0K user#P#p2.MYD
4.0K user#P#p2.MYI
4.0K user#P#p3.MYD
4.0K user#P#p3.MYI
12K user.frm
4.0K user.par
/*可以对现有表进行分区,并且会按規则自动的将表中的数据分配相应的分区
中,这样就比较好了,可以省去很多事情,看下面的操作*/
mysql> alter table aa partition by RANGE(id)
-> (PARTITION p1 VALUES less than (1),
-> PARTITION p2 VALUES less than (5),
-> PARTITION p3 VALUES less than MAXVALUE);
Query OK, 15 rows affected (0.21 sec) //对15数据进行分区
Records: 15 Duplicates: 0 Warnings: 0
//总共有15条
mysql> select count(*) from aa;
+----------+
| count(*) |
+----------+
| 15 |
+----------+
1 row in set (0.00 sec)
//删除一个分区
mysql> alter table aa drop partition p2;
Query OK, 0 rows affected (0.30 sec)
Records: 0 Duplicates: 0 Warnings: 0
//只有11条了,说明对现有的表分区成功了
mysql> select count(*) from aa;
+----------+
| count(*) |
+----------+
| 11 |
+----------+
1 row in set (0.00 sec)
LIST分区
LIST分区中每个分区的定义和选择是基于某列的值从属于一个值列表集中的一个值,而RANGE分 区是从属于一个连续区间值的集合。
//这种方式失败
mysql> CREATE TABLE IF NOT EXISTS `list_part` (
-> `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
-> `province_id` int(2) NOT NULL DEFAULT 0 COMMENT '省',
-> `name` varchar(50) NOT NULL DEFAULT '' COMMENT '名称',
-> `sex` int(1) NOT NULL DEFAULT '0' COMMENT '0为男,1为女',
-> PRIMARY KEY (`id`)
-> ) ENGINE=INNODB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1
-> PARTITION BY LIST (province_id) (
-> PARTITION p0 VALUES IN (1,2,3,4,5,6,7,8),
-> PARTITION p1 VALUES IN (9,10,11,12,16,21),
-> PARTITION p2 VALUES IN (13,14,15,19),
-> PARTITION p3 VALUES IN (17,18,20,22,23,24)
-> );
ERROR 1503 (HY000): A PRIMARY KEY must include all \
columns in the table's partitioning function
//这种方式成功
mysql> CREATE TABLE IF NOT EXISTS `list_part` (
-> `id` int(11) NOT NULL COMMENT '用户ID',
-> `province_id` int(2) NOT NULL DEFAULT 0 COMMENT '省',
-> `name` varchar(50) NOT NULL DEFAULT '' COMMENT '名称',
-> `sex` int(1) NOT NULL DEFAULT '0' COMMENT '0为男,1为女'
-> ) ENGINE=INNODB DEFAULT CHARSET=utf8
-> PARTITION BY LIST (province_id) (
-> PARTITION p0 VALUES IN (1,2,3,4,5,6,7,8),
-> PARTITION p1 VALUES IN (9,10,11,12,16,21),
-> PARTITION p2 VALUES IN (13,14,15,19),
-> PARTITION p3 VALUES IN (17,18,20,22,23,24)
-> );
Query OK, 0 rows affected (0.33 sec)
LIST分区中每个分区的定义和选择是基于某列的值从属于一个值列表集中的一个值,而RANGE分 区是从属于一个连续区间值的集合。
HASH分区
HASH分区主要用来确保数据在预先确定数目的分区中平均分布,你所要做的只是基于将要被哈希的列值指定一个列值或表达式,以及指定被分区的表将要被分割成的分区数量。
mysql> CREATE TABLE IF NOT EXISTS `hash_part` (
-> `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '评论ID',
-> `comment` varchar(1000) NOT NULL DEFAULT '' COMMENT '评论',
-> `ip` varchar(25) NOT NULL DEFAULT '' COMMENT '来源IP',
-> PRIMARY KEY (`id`)
-> ) ENGINE=INNODB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1
-> PARTITION BY HASH(id)
-> PARTITIONS 3;
Query OK, 0 rows affected (0.06 sec)
KEY分区
按照KEY进行分区类似于按照HASH分区,除了HASH分区使用的用 户定义的表达式,而KEY分区的 哈希函数是由MySQL 服务器提供。
mysql> CREATE TABLE IF NOT EXISTS `key_part` (
-> `news_id` int(11) NOT NULL COMMENT '新闻ID',
-> `content` varchar(1000) NOT NULL DEFAULT '' COMMENT '新闻内容',
-> `u_id` varchar(25) NOT NULL DEFAULT '' COMMENT '来源IP',
-> `create_time` DATE NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '时间'
-> ) ENGINE=INNODB DEFAULT CHARSET=utf8
-> PARTITION BY LINEAR HASH(YEAR(create_time))
-> PARTITIONS 3;
Query OK, 0 rows affected (0.07 sec)
子分区
子分区是分区表中每个分区的再次分割,子分区既可以使用HASH希分区,也可以使用KEY分区。这 也被称为复合分区(composite partitioning)。
- 如果一个分区中创建了子分区,其他分区也要有子分区
- 如果创建了了分区,每个分区中的子分区数必有相同
- 同一分区内的子分区,名字不相同,不同分区内的子分区名子可以相同(5.1.50不适用)
mysql> CREATE TABLE IF NOT EXISTS `sub_part` (
-> `news_id` int(11) NOT NULL COMMENT '新闻ID',
-> `content` varchar(1000) NOT NULL DEFAULT '' COMMENT '新闻内容',
-> `u_id` int(11) NOT NULL DEFAULT 0s COMMENT '来源IP',
-> `create_time` DATE NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '时间'
-> ) ENGINE=INNODB DEFAULT CHARSET=utf8
-> PARTITION BY RANGE(YEAR(create_time))
-> SUBPARTITION BY HASH(TO_DAYS(create_time))(
-> PARTITION p0 VALUES LESS THAN (1990)(SUBPARTITION s0,SUBPARTITION s1,SUBPARTITION s2),
-> PARTITION p1 VALUES LESS THAN (2000)(SUBPARTITION s3,SUBPARTITION s4,SUBPARTITION good),
-> PARTITION p2 VALUES LESS THAN MAXVALUE(SUBPARTITION tank0,SUBPARTITION tank1,SUBPARTITION tank3)
-> );
Query OK, 0 rows affected (0.07 sec)