MYSQL数据库MySQL数据库分区功能的使用教程
《MYSQL数据库MySQL数据库分区功能的使用教程》要点: 零,什么是数据库分区 一,横向分区 ALTER TABLE `yl_hospital_url` PARTITION BY RANGE(ID) ( PARTITION `p0` VALUES LESS THAN (100000),PARTITION `p1` VALUES LESS THAN (200000),PARTITION `p2` VALUES LESS THAN (300000),PARTITION `p3` VALUES LESS THAN (400000),PARTITION `p4` VALUES LESS THAN (500000),PARTITION `p5` VALUES LESS THAN (600000),PARTITION `p6` VALUES LESS THAN (700000),PARTITION `p7` VALUES LESS THAN (MAXVALUE) ) ; 分区前查询速度 分区前查询速度 二,mysql的分区 [root@BlackGhost mysql-5.1.50]# ./configure --help |grep -A 3 Partition === Partition Support === Plugin Name: partition Description: MySQL Partitioning Support Supports build: static Configurations: max,max-no-ndb ?查看一下,如果发现有上面这个东西,说明他是支持分区的,默认是打开的.如果你已经安装过了mysql的话MYSQL实例 mysql> show variables like "%part%"; +-------------------+-------+ | Variable_name | Value | +-------------------+-------+ | have_partitioning | YES | +-------------------+-------+ 1 row in set (0.00 sec) ?查看一下变量,如果支持的话,会有上面的提示的.MYSQL实例 2,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',('张',('映',0),('test1',('tank2',1) ->,('tank1',('test2',('test3',('test4',('test5',('tank3',('tank4',('tank5',('tank6',('tank7',('tank8',('tank9',('tank10',('tank11',('tank12',('tank13',('tank21',('tank42',1); Query OK,25 rows affected (0.05 sec) Records: 25 Duplicates: 0 Warnings: 0 ? [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 ? 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 ? mysql> select count(*) from aa; +----------+ | count(*) | +----------+ | 11 | +----------+ 1 row in set (0.00 sec) 3,list分区 //这种方式失败 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 '省',-> 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',1为女' -> ) ENGINE=INNODB DEFAULT CHARSET=utf8 -> PARTITION BY LIST (province_id) ( -> PARTITION p0 VALUES IN (1,24) -> ); Query OK,0 rows affected (0.33 sec) ? 4,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) 测试请参考range分区的操作MYSQL实例 5,key分区 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) 测试请参考range分区的操作MYSQL实例 6,子分区 mysql> CREATE TABLE IF NOT EXISTS `sub_part` ( -> `news_id` int(11) NOT NULL COMMENT '新闻ID',-> `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) 官方网站说不同分区内的子分区可以有相同的名字,但是mysql5.1.50却不行会提示以下错误 CREATE TABLE `year_log` ( `id` int(11) DEFAULT NULL,`money` int(11) unsigned NOT NULL,`date` datetime DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 PARTITION BY RANGE (year(date)) ( PARTITION p2007 VALUES LESS THAN (2008),PARTITION p2008 VALUES LESS THAN (2009),PARTITION p2009 VALUES LESS THAN MAXVALUE ); CREATE TABLE `daily_log` ( `id` int(11) NOT NULL,`sid` char(36) NOT NULL,`sname` char(20) DEFAULT NULL,`date` datetime NOT NULL,PRIMARY KEY (`id`,`date`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 PARTITION BY RANGE COLUMNS(`date`) (PARTITION p1 VALUES LESS THAN ('2000-01-02'),PARTITION p2 VALUES LESS THAN ('2000-01-03'),PARTITION p3 VALUES LESS THAN ('2000-01-04'),PARTITION p4 VALUES LESS THAN ('2000-01-05'),PARTITION p5 VALUES LESS THAN ('2000-01-06'),PARTITION p6 VALUES LESS THAN ('2000-01-07'),PARTITION p7 VALUES LESS THAN ('2000-01-08'),PARTITION p367 VALUES LESS THAN (MAXVALUE)); 三,分区管理 mysql> alter table user drop partition p4; 2,新增分区MYSQL实例 range添加新分区 mysql> alter table user add partition(partition p4 values less than MAXVALUE); Query OK,0 rows affected (0.06 sec) Records: 0 Duplicates: 0 Warnings: 0 ? mysql> alter table hash_part add partition partitions 4; Query OK,0 rows affected (0.12 sec) Records: 0 Duplicates: 0 Warnings: 0 ? mysql> alter table key_part add partition partitions 4; Query OK,1 row affected (0.06 sec) //有数据也会被重新分配 Records: 1 Duplicates: 0 Warnings: 0 ? mysql> alter table sub1_part add partition(partition p3 values less than MAXVALUE); Query OK,0 rows affected (0.02 sec) Records: 0 Duplicates: 0 Warnings: 0 ? mysql> show create table sub1_partG; *************************** 1. row *************************** Table: sub1_part Create Table: CREATE TABLE `sub1_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' COMMENT '时间' ) ENGINE=InnoDB DEFAULT CHARSET=utf8 !50100 PARTITION BY RANGE (YEAR(create_time)) SUBPARTITION BY HASH (TO_DAYS(create_time)) (PARTITION p0 VALUES LESS THAN (1990) (SUBPARTITION s0 ENGINE = InnoDB,SUBPARTITION s1 ENGINE = InnoDB,SUBPARTITION s2 ENGINE = InnoDB),PARTITION p1 VALUES LESS THAN (2000) (SUBPARTITION s3 ENGINE = InnoDB,SUBPARTITION s4 ENGINE = InnoDB,SUBPARTITION good ENGINE = InnoDB),PARTITION p2 VALUES LESS THAN (3000) (SUBPARTITION tank0 ENGINE = InnoDB,SUBPARTITION tank1 ENGINE = InnoDB,SUBPARTITION tank3 ENGINE = InnoDB),PARTITION p3 VALUES LESS THAN MAXVALUE (SUBPARTITION p3sp0 ENGINE = InnoDB,//子分区的名子是自动生成的 SUBPARTITION p3sp1 ENGINE = InnoDB,SUBPARTITION p3sp2 ENGINE = InnoDB)) 1 row in set (0.00 sec) 3,重新分区MYSQL实例 range重新分区? mysql> ALTER TABLE user REORGANIZE PARTITION p0,p1,p2,p3,p4 INTO (PARTITION p0 VALUES LESS THAN MAXVALUE); Query OK,11 rows affected (0.08 sec) Records: 11 Duplicates: 0 Warnings: 0 list重新分区?? mysql> ALTER TABLE list_part REORGANIZE PARTITION p0,p4 INTO (PARTITION p0 VALUES in (1,5)); Query OK,0 rows affected (0.28 sec) Records: 0 Duplicates: 0 Warnings: 0 ? mysql> ALTER TABLE key_part REORGANIZE PARTITION COALESCE PARTITION 9; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'PARTITION 9' at line 1 四,分区优点 MySQL分表、分区的区别和联系MYSQL实例 一,什么是MySQL分表,分区 二,mysql分表和分区有什么区别呢 [root@BlackGhost test]# ls |grep user alluser.MRG alluser.frm user1.MYD user1.MYI user1.frm user2.MYD user2.MYI user2.frm 简单说明一下,上面的分表呢是利用了merge存储引擎(分表的一种),alluser是总表,下面有二个分表,user1,user2.他们二个都是独 立的表,取数据的时候,我们可以通过总表来取.这里总表是没有.MYD,.MYI这二个文件的,也就是说,总表他不是一张表,没有数据,数据都放在分表里 面.我们来看看.MRG到底是什么东西MYSQL实例 [root@BlackGhost test]# cat alluser.MRG |more user1 user2 #INSERT_METHOD=LAST 从上面我们可以看出,alluser.MRG里面就存了一些分表的关系,以及插入数据的方式.可以把总表理解成一个外壳,或者是联接池. [root@BlackGhost test]# ls |grep aa aa#P#p1.MYD aa#P#p1.MYI aa#P#p3.MYD aa#P#p3.MYI aa.frm aa.par 从上面我们可以看出,aa这张表,分为二个区,p1和p3,本来是三个区,被我删了一个区.我们都知道一张表对应三个文件.MYD,.MYI,.frm.分区呢根据一定的规则把数据文件和索引文件进行了分割,还多出了一个.par文件,打开.par文件后你可以看出他记录了,这张表的分区信息,根分表中的.MRG有点像.分区后,还是一张,而不是多张表.MYSQL实例 2,数据处理上 3,提高性能上 4),实现的难易度上 三,mysql分表和分区有什么联系呢 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |