MySQL创建方式一共有四种:range、list、hash和key。
1.1 int
create table staff( id int(32) not null, code_ varchar(30), fname varchar(30), time_ date, primary key(`id`,`time_`) ) partition by range(id)( partition p0 values less than (5), partition p1 values less than (10), partition p2 values less than (15), partition p3 values less than (MAXVALUE) )
MAXVALUE:始终大于最大可能整数值的整数值。
1.2 DATE、TIME和DATETIME
使用一个对DATE、TIME或DATETIME列进行操作的函数,并返回一个整数值。
create table staff( id int(32) not null, code_ varchar(30), fname varchar(30), time_ date, PRIMARY key(`id`,`time_`) ) partition by range(year(time_))( partition p0 VALUES less than (202201), partition p1 VALUES less than (202301), partition p2 VALUES less than (202401), partition p3 VALUES less than MAXVALUE )
1.3 TIMESTAMP
在MySQL8.0中,也可以使用UNIX TIMESTAMP()函数根据TIMESTAMP列的值对表进行RANGE分区。
CREATE TABLE quarterly_report_status ( report_id INT NOT NULL, report_status VARCHAR(20) NOT NULL, report_updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) PARTITION BY RANGE ( UNIX_TIMESTAMP(report_updated) ) ( PARTITION p0 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-01-01 00:00:00') ), PARTITION p1 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-04-01 00:00:00') ), PARTITION p2 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-07-01 00:00:00') ), PARTITION p3 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-10-01 00:00:00') ), PARTITION p4 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-01-01 00:00:00') ), PARTITION p5 VALUES LESS THAN ( UNIX_TIMESTAMP('2010-01-01 00:00:00') ), PARTITION p6 VALUES LESS THAN (MAXVALUE) );
1.4 非int
COLUMNS关键字可定义非integer范围及多列范围,不过需要注意COLUMNS括号内只能是列名,不支持函数;多列范围时,多列范围必须呈递增趋势:
-- 单列 create table staff( id int(32) not null, code_ varchar(30), fname varchar(30), time_ varchar(30), PRIMARY key(`id`,`time_`) ) partition by range columns(time_)( partition p0 VALUES less than ('202201'), partition p1 VALUES less than ('202301'), partition p2 VALUES less than ('202401'), partition p3 VALUES less than MAXVALUE ) --多列 create table stafft( one varchar(30), two varchar(30) ) partition by range columns(one,two)( partition p0 values less than ('0','10'), partition p1 values less than ('10','20'), partition p2 values less than ('20','30'), partition p3 values less than (maxvalue,maxvalue) )
2.1 int
LIST分区通过使用“PARTITION BY LIST(expr)”来实现,其中“expr”是某列值或一个基于某个列值、并返回一个整数值的表达式,然后通过“VALUES IN (value_list)”的方式来定义每个分区,其中“value_list”是一个通过逗号分隔的整数列表。
假定有20个店铺,分布在4个有经销权的地区,如下表所示:
地区 | 店铺编号 |
---|---|
北区 | 3, 5, 6, 9, 17 |
东区 | 1, 2, 10, 11, 19, 20 |
西区 | 4, 12, 13, 14, 18 |
中心区 | 7, 8, 15, 16 |
CREATE TABLE employees ( id INT NOT NULL, fname VARCHAR(30), lname VARCHAR(30), hired DATE NOT NULL DEFAULT '1970-01-01', separated DATE NOT NULL DEFAULT '9999-12-31', job_code INT, store_id INT ) PARTITION BY LIST(store_id) ( PARTITION pNorth VALUES IN (3,5,6,9,17), PARTITION pEast VALUES IN (1,2,10,11,19,20), PARTITION pWest VALUES IN (4,12,13,14,18), PARTITION pCentral VALUES IN (7,8,15,16) );
2.2 非int
与Range相同,添加COLUMNS关键字可支持非整数和多列。
如果试图插入列值(或分区表达式的返回值)不在分区值列表中的一行时,那么“INSERT”查询将失败并报错。
当插入多条数据出错时,如果表的引擎支持事务(Innodb),则不会插入任何数据;如果不支持事务,则出错前的数据会插入,后面的不会执行。
3.1 HASH
Hash分区主要用来确保数据在预先确定数目的分区中平均分布,Hash括号内只能是整数列或返回确定整数的函数。
Hash分区通过使用“PARTITION BY HASH(expr)”来实现,其中“expr”是一个返回整数的表达式。也可以是一个列名,但是类型必须是MySQL的整数类型之一。使用PARTITIONS num设置分区个数,如不设置默认为1,其中num是一个非负的整数。
create table staff( id int(32) not null, code_ varchar(30), fname varchar(30), time_ varchar(30), PRIMARY key(`id`,`time_`) ) partition by hash(id) partitions 3;
3.2 LINEAR HASH(官方文档)
与常规哈希的区别在于,线性哈希功能使用的一个线性的2的幂(powers-of-two)运算法则,而常规哈希使用的是求哈希函数值的模数。但是会有热点区的问题,因为线性哈希给每个区分配的会不均匀,分配到较多的内容时,其访问量就会较多,从而成为热点区。
create table staff( id int(32) not null, code_ varchar(30), fname varchar(30), time_ varchar(30), PRIMARY key(`id`,`time_`) ) partition by linear hash(id) partitions 3;
4.1 KEY
Key分区与Hash分区很相似,Key调用自己内部的Hash函数,定义时把Hash关键字替换成Key即可,同样Key分区也有对应与线性Hash的线性Key分区方法。Key不局限于整数类型。
当表存在主键或唯一索引时可省略Key括号内的列名,Mysql将按照主键-唯一索引的顺序选择,当找不到唯一索引时报错(MySQL 8.0)。
create table staff( id int(32) not null, code_ varchar(30), fname varchar(30), time_ varchar(30), PRIMARY key(`id`,`time_`) ) partition by key(time_) partitions 3;
4.2 LINEAR KEY
影响与Linear Hash一样,请参考上文中的Linear Hash。
create table staff( id int(32) not null, code_ varchar(30), fname varchar(30), time_ varchar(30), PRIMARY key(`id`,`time_`) ) partition by linear key(id) partitions 3;
1.1 在最后追加分区
ALTER TABLE staff ADD PARTITION (PARTITION p4 VALUES LESS THAN (12));
当已有分区最后是MAXVALUE的时候不可用。报错:1481 - MAXVALUE can only be used in last partition definition
1.2 创建表之后修改分区
表已有数据,这种做法,运行时间会比较长。建议新建表然后导入数据。修改分区会覆盖之前建立的分区。
alter table staff partition by range(id) ( partition p0 values less than (5), partition p1 values less than (10), partition p2 values less than (15), partition p3 values less than (MAXVALUE) );
1.3 分区
create table staff( id int(32) not null, code_ varchar(30), fname varchar(30), time_ varchar(20), primary key(`id`,`time_`) ) partition by range(id)( partition p0 values less than (5), partition p1 values less than (10), partition p2 values less than (15), partition p3 values less than (MAXVALUE) ) -- p2分为p4和p2 alter table staff reorganize partition p2 into ( partition p4 values less than (12), partition p2 values less than (15) )
2.1 drop
删除分区的同时也会该分区内的删除数据。
alter table staff drop partition p0;
常规HASH和线性HASH的增加收缩分区的原理是一样的。增加和收缩分区后原来的数据会根据现有的分区数量重新分布。HASH分区不能删除分区,所以不能使用DROP PARTITION操作进行分区删除操作;
通过ALTER TABLE … COALESCE PARTITION num来合并分区,这里的num是减去的分区数量;
通过ALTER TABLE … ADD PARTITION PARTITIONS num来增加分区,这里是num是在原先基础上再增加的分区数量。
3.1 合并分区
减少分区后数据会根据现有的分区进行重新分配。
alter table staff coalesce partition 3;
3.2 增加分区
增加分区之后数据会相应进行调整。
alter table tblinhash add partition partitions 4;
3.3 移除分区
移除分区的定义不会删除数据(所有分区移除)。
alter table staff remove partitioning
4.1 查询分区表中各个分区的数据量
select partition_name,table_rows from information_schema.partitions where table_name='staff'
4.2 查询某个分区信息
select * from staff partition(p1)
4.3 查询的时候使用到分区
如果查询是基于分区表的话,会显示查询将访问的分区。在5.7以前的版本中,想要显示partitions需要使用explain partitions命令;想要显示filtered需要使用explain extended命令。在5.7版本后,默认explain直接显示partitions和filtered中的信息。
explain select * from staff where id = 6
普通表一个.frm和一个.idb 而分区表一个.frm和多个.idb文件
.frm:表结构的文件
.ibd:表数据和索引的文件。该表的索引(B+树)的每个非叶子节点存储索引,叶子节点存储索引和索引对应的数据。
报错:1503 - A PRIMARY KEY must include all columns in the table's partitioning function (prefixed columns are not considered).