CREATE TABLE members (id INT,joined DATE NOT NULL)PARTITION BY RANGE COLUMNS(joined) (PARTITION a VALUES LESS THAN ("1960-01-01"),PARTITION b VALUES LESS THAN ("1970-01-01"),PARTITION c VALUES LESS THAN ("1980-01-01"),PARTITION d VALUES LESS THAN ("1990-01-01"),PARTITION e VALUES LESS THAN MAXVALUE);1.插入测试数据
insert into members(id,joined) values(1,"1950-01-01"),(1,"1960-01-01"),(1,"1980-01-01"),(1,"1990-01-01");2.查询分区数据分布
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="members";当前有5个分区只插入了4条记录,其中C分区是没有记录的,结果和实际一样。
3.分析执行计划
explain select id,joined from tb_partition.members where joined=YEAR(now());explain select id,joined from tb_partition.members where joined="1963-01-01";
第一条查询使用了函数导致查询没有走具体的分区而是扫描的所有的分区,而第二条查询执行语句查找具体的分区。
2.多个字段组合分区
CREATE TABLE rcx (a INT,b INT)PARTITION BY RANGE COLUMNS(a,b) (PARTITION p0 VALUES LESS THAN (5,10),PARTITION p1 VALUES LESS THAN (10,20),PARTITION p2 VALUES LESS THAN (15,30),PARTITION p3 VALUES LESS THAN (MAXVALUE,MAXVALUE));注意:多字段的分区键比较是基于数组的比较。它先用插入的数据的第一个字段值和分区的第一个值进行比较,如果插入的第一个值小于分区的第一个值那么就不需要比较第二个值就属于该分区;如果第一个值等于分区的第一个值,开始比较第二个值同样如果第二个值小于分区的第二个值那么就属于该分区。
例如:
insert into rcx(a,b)values(1,20),(10,15),(10,30);第一组值:(1,20);1<5所以不需要再比较20了,该记录属于p0分区。
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="rcx";
注意:RANGE COLUMN的多列分区第一列的分区值一定是顺序增长的,不能出现交叉值,第二列的值随便,例如以下分区就会报错
PARTITION BY RANGE COLUMNS(a,b) (PARTITION p0 VALUES LESS THAN (5,10),PARTITION p1 VALUES LESS THAN (10,20),PARTITION p2 VALUES LESS THAN (8,30),PARTITION p3 VALUES LESS THAN (MAXVALUE,MAXVALUE));由于分区P2的第一列比P1的第一列要小,所以报错,后面的分区第一列的值一定要比前面分区值要大,第二列没规定。
CREATE TABLE listvar (id INT NOT NULL,hired DATETIME NOT NULL)PARTITION BY LIST COLUMNS(hired) (PARTITION a VALUES IN ("1990-01-01 10:00:00","1991-01-01 10:00:00"),PARTITION b VALUES IN ("1992-01-01 10:00:00"),PARTITION c VALUES IN ("1993-01-01 10:00:00"),PARTITION d VALUES IN ("1994-01-01 10:00:00"));ALTER TABLE listvar ADD INDEX ix_hired(hired);INSERT INTO listvar() VALUES(1,"1990-01-01 10:00:00"),(1,"1991-01-01 10:00:00"),(1,"1992-01-01 10:00:00"),(1,"1993-01-01 10:00:00");LIST COLUMNS分区对分整形字段进行分区就无需使用函数对字段处理成整形,所以对非整形字段进行分区建议选择COLUMNS分区。
EXPLAIN SELECT * FROM listvar WHERE hired="1990-01-01 10:00:00";
2.多字段分区
CREATE TABLE listvardou (id INT NOT NULL,hired DATETIME NOT NULL)PARTITION BY LIST COLUMNS(id,hired) (PARTITION a VALUES IN ( (1,"1990-01-01 10:00:00"),(1,"1991-01-01 10:00:00") ),PARTITION b VALUES IN ( (2,"1992-01-01 10:00:00") ),PARTITION c VALUES IN ( (3,"1993-01-01 10:00:00") ),PARTITION d VALUES IN ( (4,"1994-01-01 10:00:00") ));ALTER TABLE listvardou ADD INDEX ix_hired(hired);INSERT INTO listvardou() VALUES(1,"1990-01-01 10:00:00"),(1,"1991-01-01 10:00:00"),(2,"1992-01-01 10:00:00"),(3,"1993-01-01 10:00:00");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="listvardou";
EXPLAIN SELECT * FROM listvardou WHERE id=1 and hired="1990-01-01 10:00:00";
由于分区是组合字段,filtered只有50%,对于组合分区索引也最好是建组合索引,其实如果能通过id字段刷选出数据,单独建id字段的索引也是有效果的,但是组合索引的效果是最好的,其实和非分区键索引的概念差不多。
ALTER TABLE listvardou ADD INDEX ix_hired1(id,hired);
备注:文章中的示例摘自mysql官方参考手册
三、移除表的分区
ALTER TABLE tablenameREMOVE PARTITIONING ;注意:使用remove移除分区是仅仅移除分区的定义,并不会删除数据和drop PARTITION不一样,后者会连同数据一起删除