首页 > 代码库 > Mysql --- 分区表
Mysql --- 分区表
概念:由一个或多个物理分区组成的表
类型:RANGE HASH LIST KEY
下面主要实现RANGE和HASH
一.RANGE类型的分区表
1.按照主键分区
DROP TABLE IF EXISTS p_user;CREATE TABLE p_user( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(225), login_date DATETIME)ENGINE=INNODB PARTITION BY RANGE (id)(PARTITION p0 VALUES LESS THAN (10),PARTITION p1 VALUES LESS THAN (20),PARTITION p2 VALUES LESS THAN (30),PARTITION p3 VALUES LESS THAN MAXVALUE)
分区表p_user,小于10的id存储在p0分区中,10到20之间的id存储在p1中,以此类推,大于30的id存储在p3中。
如果去掉 PARTITION p3 VALUES LESS THAN MAXVALUE ,则插入id 超过30的数据会报错:Table has no partition for value 30
2.按照日期分区
DROP TABLE IF EXISTS p_user;CREATE TABLE p_user( name VARCHAR(225), login_date DATETIME)ENGINE=INNODB PARTITION BY RANGE (YEAR(login_date))(PARTITION p_2014 VALUES LESS THAN (2015),PARTITION p_2015 VALUES LESS THAN (2016),PARTITION p_2016 VALUES LESS THAN (2017),PARTITION p_max VALUES LESS THAN MAXVALUE)
查看分区查询情况:
explain partitions select * from p_user where login_date >= ‘2017-1-1‘
可见是从p_max分区中读的数据
二.HASH类型的分区表
1.按照id分区,且均匀分布数据
DROP TABLE IF EXISTS p_user;CREATE TABLE p_user( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(225), login_date DATETIME)ENGINE=INNODB PARTITION BY HASH (id)PARTITIONS 4
EXPLAIN PARTITIONS SELECT * FROM p_user WHERE id = 1015
选择分区规则是:hash后面的计算值 除以 分区数目 余数就是分区所在。(1015/4 余数3 所以在p3)。所以hash类型的分区表可以保证数据均匀分布。
2.按照id分区,且以满1000000数据为换分区的条件
说明:第一分区存满1000000数据,则换下一分区,当四个分区都满1000000数据后,回到第一分区重新开始,当第一分区再次满1000000数据后,继续换下一分区,以此循环
DROP TABLE IF EXISTS p_user;CREATE TABLE p_user( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(225), login_date DATETIME)ENGINE=INNODB PARTITION BY HASH (id DIV 1000000)PARTITIONS 4
三.效率测试
准备两张表
-- 有分区的表DROP TABLE IF EXISTS p_user;CREATE TABLE p_user( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(225), login_date DATETIME)ENGINE=INNODB PARTITION BY HASH (id)PARTITIONS 4-- 没有分区的表DROP TABLE IF EXISTS user;CREATE TABLE user( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(225), login_date DATETIME)ENGINE=INNODB
两张表分别填充1600万左右的数据
1.测试(1)
select * from p_user where id = 15000000;select * from user where id = 15000000;
查询耗时相当,因为id是主键索引,所以无法体现分区表的优势
2.测试(2)
把p_user 和 user 表id字段的主键和自增属性去掉,且把id为15000000行对应的name改成‘httt‘
select * from p_user where id = 15000000;select * from user where id = 15000000;
原因:第一条查询会到对应的分区里查找数据,所以更快
explain partitions select * from p_user where id = 15000000;
3.测试(3)
和测试(2)的场景一样
select * from p_user where name = ‘httt‘ and id = 15000000;select * from user where name = ‘httt‘ and id = 15000000;
原因:第一条查询会到对应的分区里查找数据,所以更快
4.测试(4)
和测试(2)的场景一样
select * from p_user where name = ‘httt‘;select * from user where name = ‘httt‘;
可见分区表的耗时比多了两秒,多次执行,结果都是分区表耗时长。原因:条件字段不是分区字段,所以查询每个分区的数据
explain partitions select * from p_user where name = ‘httt‘;
5.测试总结
---按照索引列分区,那么对查询优化几乎没影响
---按照非索引列分区,则查询条件中用了分区列,能提高查询速度,反之,会降低查询速度
Mysql --- 分区表