【转自star_glm的博客】前言在介绍交换分区之前,我们先了解下mysql分区。数据库分区有两种类型:水平分区和垂直分区。而MySQL暂时不支持垂直分区,接下来要说的就是水平分区了。水平分区的意思是:按行对表进行分区。例如:按时间分区,一年一个分区等。在MySQL中,分区是可以交换的,分区表中的分区中的数据可以与普通表交换。交换分区的实现1.交换分区的语法altertableptexchangepartitionpwithtablent;解释:交换分区表pt的分区p和一个普通表nt的数据。交换前提:普通表nt不是临时表,也不是分区表。表结构与分区表pt的结构一致。普通表没有外键引用。如果公共表nt不为空。在MySQL5.6及之前的版本中,必须在分区范围内;MySQL5.7以后,不能再在它的分区范围内,依然会成??功存储在分区中。2.实验交换分区(1)创建分区表并插入数据#createapartitiontableeCREATETABLEe(idINTNOTNULL,fnameVARCHAR(30),lnameVARCHAR(30))PARTITIONBYRANGE(id)(PARTITIONp0VALUESLESSTHAN(50),PARTITIONp1VALUESLESSTHAN(100),PARTITIONp2VALUESLESSTHAN(150),PARTITIONp3VALUESLESSTHAN(MAXVALUE));#插入几条数据到分区表eINSERTINTOeVALUES(1669,"Jim","Smith"),(337,"Mary","Jones"),(16,"Frank","White"),(2005,"Linda","Black");(2)创建与分区表e2结构相同的普通表e2#Createatablee2mysql>createtablee2likee;#删除分区表e2表e2,将其设为普通表mysql>altertablee2removepartitioning;(3)查看表e每个分区有多少行mysql>selectPARTITION_NAME,TABLE_ROWS->FROMINFORMATION_SCHEMA.PARTITIONS->WHERETABLE_NAME='e';------+------------+|PARTITION_NAME|TABLE_ROWS|+----------------+-----------+|p0|1||p1|0||p2|0||p3|3|+----------------+----------+4rowsinset(0.00sec)(4)将表e的分区p0交换到普通表e2mysql>altertableeeexchangepartitionp0withtablee2;(5)查看结果#表e中分区P0的数据为no更长的mysql>SELECTPARTITION_NAME,TABLE_ROWS->FROMINFORMATION_SCHEMA.PARTITIONS->WHERETABLE_NAME='e';+----------------+------------+|PARTITION_NAME|TABLE_ROWS|+----------------+------------+|p0|0||p1|0||p2|0||p3|3|+----------------+------------+4rowsinset(0.00sec)#从表e到表e2有一行p0分区的数据mysql>SELECT*FROMe2;+----+------+------+|id|fname|lname|+----+-------+--------+|16|Frank|White|+----+--------+--------+1rowinset(0.00sec)发现,将表e的分区p0中的数据移动到上面例子中的表e2中,就是和一个普通的空表交换一个分区,相当于把一个分区的数据移出,一般用于数据归档。同样,交换分区也可以在一个分区和一个非空的普通表之间进行交换,这样普通表中的数据就会迁移到指定分区,指定分区中的数据就会迁移到普通表.操作如下:(6)向分区表e的p0添加另一条数据#向表e添加分区p0范围内的一条数据mysql>INSERTINTOeVALUES(41,"Michael","Green");QueryOK,1rowaffected(0.05sec)#确认插入的数据确实存储在分区p0mysql>SELECTPARTITION_NAME,TABLE_ROWS->FROMINFORMATION_SCHEMA.PARTITIONS->WHERETABLE_NAME='e';+-----------------+-------------+|PARTITION_NAME|TABLE_ROWS|+----------------+------------+|p0|1||p1|0||p2|0||p3|3|+----------------+-------------+4rowsinset(0.00sec)(7)执行exchangepartitionmysql>altertableeeexchangepartitionp0withtablee2;QueryOK,0rowsaffected(0.28sec)(8)查看结果#在将表e的p0交换到表e2的一条数据之前,现在又回到表emysql>SELECT*FROMe;+------+--------+--------+|id|fname|lname|+------+-------+-------+|16|弗兰克|怀特||1669|吉姆|史密斯||337|玛丽|琼斯||2005|琳达|布莱克|+------+--------+--------+4rowsinset(0.00sec)mysql>SELECT*FROMe2;+----+-------+--------+|id|fname|lname|+----+--------+------+|41|Michael|Green|+----+--------+-------+1rowinset(0.00sec)由此可以看出表e的p0的数据和表e2已被交换!该场景可用于将普通表数据移动到分区表的某个分区。但是需要注意一点:如果普通表的数据不在要交换的分区范围内,上面交换分区的语法是无法执行成功的!请看下面的操作。(9)向普通表e2中插入一段超出表ep0范围的数据,执行上面的交换语句mysql>INSERTINTOe2VALUES(51,"Ellen","McDonald");QueryOK,1rowaffected(0.08sec)mysql>altertableeexchangepartitionp0withtablee2;ERROR1707(HY000):Foundrowthatdoesnotmatchthepartition在MySQL5.6中无法解决该问题;在MySQL5.7.5中,增加了一个WITHOUTVALIDATION选项来解决上述错误。操作如下:mysql>ALTERTABLEeEXCHANGEPARTITIONp0WITHTABLEe2WITHOUTVALIDATION;QueryOK,0rowsaffected(0.02sec)查看结果:表e的p0中也存储了#id51的数据mysql>select*fromepartition(p0);+------+--------+----------+|id|fname|lname|+------+--------+----------+|41|Michael|Green||51|Ellen|McDonald|+-----+--------+---------+mysql>SELECT*FROMe2;+----+--------+------+|id|fname|lname|+----+---------+--------+|16|Frank|White|+----+--------+--------+1rowinset(0.00sec)总结通过上面的实践操作发现,MySQL的swap分区的功能有两种适用场景:将分区表的某个分区与空的普通表进行交换,从而将分区表分区的数据移出。分区表的一个分区与一个非空的普通表交换,使普通表的数据移动到分区表的指定分区。
