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出现错误:ERROR 1045 (28000): Access denied for user ‘root‘@‘localhost‘ (using password: YES)(代码片段