就是把很大数据量的数据拆分存在不同的数据文件中,来达到提升查询效率的做法。每个分区表都有一个句柄对象,mysql通过对句柄对象的管理使得多个底层的分区表看上去就是一个逻辑表
总结:可伸缩性,可管理性,提高数据库查询效率
range分区:一般按照数据的范围来分区,但是是连续的,比如按照年龄来分
mysql> create table t4 (id int, name varchar(20),age int(3))
-> partition by range(age) #确定按照age字段分区
-> (
-> partition p01 values less than (20),
-> partition p02 values less than (30), #age在[20,30)
-> partition p03 values less than (maxvalue) #age在 [30,maxvalue
-> );
list分区:将一些离散的值放在一个分区。如将商品id为1,2,3放在一个分区。注意在5.1中只能使用匹配整数,5.5+可以使用字符串和日期作为分区定义列
mysql > create table t5 (id int, type int(3), name varchar(20), price float(10,2))
-> partition by list (type)
-> (
-> partition p01 values in (1,2,3),
-> partition p02 values in (4,5,6),
-> partition p03 values in (7,8,9,0)
-> );
hash分区:基于列值,或者表达式进行hash算法。在MySQL cluster 中分区是自动的,默认是和ndb_node数量相同的。
mysql> create table t6 (id int, type int(3), name varchar(20), price float(10,2))
-> partition by hash (type)
-> partitions 4; #分区个数
Linear hash线性hash:使用线性2次幂运算法则,优点在于增加、删除、合并和拆分分区更快捷,利于处理含有很大数据的表(1T)。但它的算法不很均匀,有可能导致hotspot nodes的问题
mysql> create table t7 (id int, type int(3), name varchar(20), price float(10,2))
-> partition by linear hash (type) #只是比hash分区多个linear关键字
-> partitions 4; #分区个数
key分区:基本和hash相同,不常使用
mysql> create table t7 (id int, type int(3), name varchar(20), price float(10,2))
-> partition by linear key (type)
-> partitions 4; #分区个数
多列分区:在5.5+之后支持。columns关键字允许字符串和日期作为分区定义列,分区可以根据多列的值,匹配数据优先级从左至右。
mysql> create table t8 (id int, type int(3), name varchar(20), price float(10,2), online date)
-> partition by range columns (type,online)
-> (
-> partition p01 values less than (5,'2004-01-01'),
-> partition p02 values less than (5,'2012-01-01'),
-> partition p03 values less than (10,'2016-01-01'),
-> partition p04 values less than (maxvalue,maxvalue)
-> );
子分区:在分区的基础在分区。子分区可以用于特别大的表,在多个磁盘间分配数据和索引,提升IO效率
root@localhost: testx 12:00 > create table t11 (id int, type int(3), name varchar(20), price float(10,2), online date)
-> partition by list (type)
-> subpartition by hash (year(online))
-> (
-> partition p0 values in (1,2,3)
-> (
-> subpartition s0
-> data directory = '/data/sda/data'
-> index directory = '/data/sda/index',
-> subpartition s1
-> data directory = '/data/sdb/data'
-> index directory = '/data/sdb/index'
-> ),
-> partition p1 values in (4,6,5)
-> (
-> subpartition s2
-> data directory = '/data/sdc/data'
-> index directory = '/data/sdc/index',
-> subpartition s3
-> data directory = '/data/sdd/data'
-> index directory = '/data/sdd/index'
-> )
-> );
注意语法:每个分区必须都相同数量的子分区;有一个分区定义子分区其他分区都得定义
修改表的分区方式,或者对已存在的表但没有表分区新增表分区
建议在生产环境中尽量不要修改分区,alter会读出存在旧表中的数据,再存入新定义的表中,过程IO将很大,而且全表都会锁住。
alter table t1 partition by hash(type) partitions 3;
range & list分区删除指定的分区
删除分区数据:truncate保留分区结构,只删除分区里面的数据,效率比delete高。drop直接整个删除,包括分区和里面的数据。其中truncate用的很大
alter table t1 drop partition p01;
alter table t1 truncate partition p01;
range分区增加分区表:注意添加的数据范围必须在比当前最大值还大
alter table t1 add partition (partition p2 values less than (2016) );
list分区增加分区:新增的分区中的value不能存在现有的分区values中
alter table t5 add partition (partition p04 values in (10,11));
分区重组:大分区拆分成多个小分区,把小分区综合成大分区
对于range分区,只能重新组织相邻的分区;
拆分:mysql> alter table t1 reorganize partition p03 into (
-> partition p12 values less than (30),
-> partition p13 values less than (maxvalue)
-> );
合并:alter table t4 reorganize partition p12,p13 into ( partition p03 values less than (maxvalue) );
hash和key分区管理
缩减:alter table t6 coalesce partition 2; # coalesce中文意:合并
增加:alter table t6 add partition partitions 2; #增加了,不是增加到
重建分区:整理分区碎片,先抽取数据,之后重建分区,最后导回
alter table t4 rebuild partition p01,p02;
优化分区:如果从分区中删除了大量的行,或者对text,blob等做了大量的修改,此时需要整理数据文件碎片,相比较rebuild性能消耗小些
alter table t4 optimize partition p01,p02;
检测修复分区:
alter table t1 check partition p01,p02;
alter table t1 repair partition p01,p02;
使用合并表注意点:
使用between范围查找时,会在各子表查询,不会像分区表先确定范围再到子分区查找。
在合并表做唯一索引或主键时,一旦找到数据,就停止查找。
扫描子分区是按照表定义时表的顺序进行查找的
合并表很容易管理子表,添加时,删除定义再重新定义。
在使用between范围查找时,查询应根据原来实际的数据类型来作为条件
通过explain partitions select … \G;来确定分区的使用情况。
mysql> explain partitions select * from t5 where type=2\G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t5
partitions: p01 #注意这里只使用p01,如果不加where条件时将检索整个分区
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 2
Extra: Using where