首页 > 代码库 > 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 --- 分区表