Mysql --- 分区表

Posted 涛涛taotao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 --- 分区表的主要内容,如果未能解决你的问题,请参考以下文章

从mysql的片段中加载ListView

详解MySQL分区表

连接MySQL出现错误:ERROR 1045 (28000): Access denied for user ‘root‘@‘localhost‘ (using password: YES)(代码片段

mysql分区表

使用 json rereiver php mysql 在片段中填充列表视图

MySQL表分区