常规HASH和线性HASH的增加收缩分区的原理是一样的。增加和收缩分区后原来的数据会根据现有的分区数量重新分布。HASH分区不能删除分区,所以不能使用DROP PARTITION *** 作进行分区删除 *** 作;
只能通过ALTER TABLE ... COALESCE PARTITION num来合并分区,这里的num是减去的分区数量;
可以通过ALTER TABLE ... ADD PARTITION PARTITIONS num来增加分区,这里是null是在原先基础上再增加的分区数量。
1.合并分区
减去3个分区
ALTER TABLE tblinhash COALESCE PARTITION 3
SELECT PARTITION_NAME,PARTITION_METHOD,PARTITION_EXPRESSION,PARTITION_DESCRIPTION,TABLE_ROWS,SUBPARTITION_NAME,SUBPARTITION_METHOD,SUBPARTITION_EXPRESSION
FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA=SCHEMA() AND TABLE_NAME='tblinhash'
注意:减去两个分区后,数据根据现有的分区进行了重新的分布,以'2003-04-14'为例:POWER(2, CEILING( LOG(2,3) ))=4,2003&(4-1)=3,3>=3,3&(CEILING(3/2)-1)=1,所以现在的'2003-04-14'这条记录由原来的p3变成了p1
2.增加分区
增加4个分区
ALTER TABLE tblinhash add PARTITION partitions 4
SELECT PARTITION_NAME,PARTITION_METHOD,PARTITION_EXPRESSION,PARTITION_DESCRIPTION,TABLE_ROWS,SUBPARTITION_NAME,SUBPARTITION_METHOD,SUBPARTITION_EXPRESSION
FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA=SCHEMA() AND TABLE_NAME='tblinhash'
当在3个分区的基础上增加4个分区后,‘2003-04-14’由原来的p1变成了p3,而另一条记录由原来的p2变成了p6
一、背景
话说风和日丽的一天,为提高随着业务增长的大表(3510449行吧)的访问效率,于是决定对表分区,记录如下。
二、实 ***
结合业务,若干条记录会集中在一个日期,查询时也往往只查询一个日期内的数据,于是选取分区字段为时间。
创建分区 比如
CREATE TABLE message_all (
id int(10) NOT NULL AUTO_INCREMENT,
......
createtime datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间'
PRIMARY KEY ( id , createtime )
) ENGINE=InnoDB DEFAULT CHARSET=utf8
PARTITION BY RANGE (YEAR(createtime))
(PARTITION p2015 VALUES LESS THAN (2016) ENGINE = InnoDB,
PARTITION p2016 VALUES LESS THAN (2017) ENGINE = InnoDB,
PARTITION p2017 VALUES LESS THAN (2018) ENGINE = InnoDB,
PARTITION p2018 VALUES LESS THAN MAXVALUE ENGINE = InnoDB)
不过我们表已经有了当然不能这么建,除非你想导一次数据。
如下 *** 作 :
1、
ALTER TABLE message_all PARTITION BY RANGE (to_days(createtime))
(
PARTITION p2015 VALUES LESS THAN (to_days('2016-01-01')),
PARTITION p2016 VALUES LESS THAN (to_days('2017-01-01')),
PARTITION p2017 VALUES LESS THAN (to_days('2018-01-01')),
PARTITION p2018 VALUES LESS THAN MAXVALUE
)
或者
2、ALTER TABLE message_all PARTITION BY RANGE (YEAR(createtime))
(
PARTITION p2015 VALUES LESS THAN (YEAR('2016-01-01'))
)
然后追加。
ALTER TABLE message_all ADD PARTITION
(
PARTITION p2016 VALUES LESS THAN (YEAR('2017-01-01')),
PARTITION p2017 VALUES LESS THAN (YEAR('2018-01-01')),
PARTITION p2018 VALUES LESS THAN MAXVALUE
)
这里会有几种错误情况:
1、ALTER TABLE message_all PARTITION BY RANGE (to_days(createtime))
[Err] 1492 - For RANGE partitions each partition must be defined
解释:必须指定至少一个分区。
2、[Err] 1492 - A PRIMARY KEY must include all columns in the table's partitioning function
解释:分区字段必须是主键之一。
3、[Err] 1492 - Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed
解释:分区字段为timestamp,换成datetime。
4、[Err] 1526 - Table has no partition for value xxxx
解释:用追加方式第一次必须覆盖目前所有数据。
总结:
1、创建时必须指定至少一个分区。
2、key必须为主键之一。
3、RANGE处必须为INT型,时间字段用函数转——YEAR()、YEARWEEK()、TO_DAYS()。
4、THAN处必须为INT型,时间字段用函数转——TO_DAYS、TO_SECONDS()、UNIX_TIMESTAMP()。
5、它就是以两个INT比大小划分的文件。
6、所有ENGINE必须一样。
7、范围分区添加只能在最大值后面追加。
8、分区是有上限的貌似1024个。
用到的其他 *** 作
1、删除分区(直接扔掉分区文件,数据也没了)
ALTER TABLE message_all DROP PARTITION p2016
2、清空分区数据
ALTER TABLE message_all TRUNCATE PARTITION p2017
3、重定义(可实现:分区拆分、合并、重命名)
ALTER TABLE message_all REORGANIZE PARTITION p201601,p201602,p201603,p201604 INTO
(
PARTITION p2016012 VALUES less than(TO_DAYS('2016-03-01')),
PARTITION p2016034 VALUES less than(TO_DAYS('2016-05-01'))
)
检查/查看你的分区
1、SHOW TABLE STATUS LIKE 'message_all'
2、SELECT * FROM information_schema.partitions WHERE table_name='message_all'
3、SHOW CREATE TABLE message_all
4、EXPLAIN SELECT COUNT(1) FROM message_all WHERE createtime>= '2016-01-01' AND createtime <'2016-12-30'如果用到了分区partitions里会有显示。
5、指定分区查
SELECT COUNT(1) FROM message_all PARTITION (p2016) 表别名 WHERE ......
到这里就结束啦,土豆白。
一些概念
水平分区Partition有以下几种模式
如果是mysql5.5还是可以做到的,5.1不行CREATE TABLE part_date
( c1 bigint(20) unsigned NOT NULL AUTO_INCREMENT,
c2 varchar(40) not null default '',
c3 datetime not NULL,
PRIMARY KEY (c1,c3),
KEY partidx(c3)) ENGINE=InnoDB DEFAULT CHARSET=utf8
partition by range COLUMNS(c3)
(
PARTITION p201012 VALUES LESS THAN ('2011-01-01 06:00:00'),
PARTITION p201101 VALUES LESS THAN ('2011-01-01 12:00:00'),
PARTITION p201102 VALUES LESS THAN ('2011-01-01 18:00:00'),
PARTITION p201103 VALUES LESS THAN ('2011-01-01 23:59:59'),
PARTITION p201912 VALUES LESS THAN MAXVALUE )
然后用函数录入数据
DELIMITER $$
DROP PROCEDURE IF EXISTS `load_data` $$
CREATE DEFINER=`root`@`%` PROCEDURE `load_data`()
BEGIN
declare v int default 0
while v <10000
do
insert into part_date(c2,c3)
values (uuid(),'2011-01-01 01:00:00')
insert into part_date(c2,c3)
values (uuid(),'2011-01-01 03:00:00')
insert into part_date(c2,c3)
values (uuid(),'2011-01-01 05:01:00')
insert into part_date(c2,c3)
values (uuid(),'2011-01-01 07:01:00')
insert into part_date(c2,c3)
values (uuid(),'2011-01-01 15:01:00')
insert into part_date(c2,c3)
values (uuid(),'2011-01-01 16:01:00')
insert into part_date(c2,c3)
values (uuid(),'2011-01-01 17:01:00')
insert into part_date(c2,c3)
values (uuid(),'2011-01-01 18:01:00')
insert into part_date(c2,c3)
values (uuid(),'2011-01-01 19:01:00')
set v = v + 1
end while
END $$
DELIMITER
分区
explain partitions select count(*) from part_date where c3 >date '2011-01-01 06:02:00' and c3 <date '2011-01-01 08:02:00'
看一下只走了p201101分区
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)