分区
分区是指根据一定的规则,数据库把一个表分解成多个更小的、更容易管理的部分。就访问数据库的应用而言,逻辑上只有一个表或一个索引,但是实际上这个表可能由数十个物理分区对象组成,每个分区都是一个独立的对象,可以独自处理,可以作为表的一部分进行处理。分区对应用来说是完全透明的,不影响应用的业务逻辑。
分区有利于管理非常大的表,它采用了“分而治之”的逻辑,分区引入了分区键(partition key)的概念,分区键用于根据某个区间值(或者范围值)、特定值列表、或者HASH函数值执行数据的聚集,让数据根据规则分布在不同的分区中,让一个大对象变成一些小对象。
分区表逻辑上还是只有一张表,但是实际上是由多个物理分区对象组成。
MySQL分区即可以对数据进行分区也可以对索引进行分区。
分区类型
- range分区:基于一个给定的连续区间范围(区间要求连续并且不能重叠),使用VALUES LESS THAN 进行分区定义
- list分区:类似于range分区,区别在于list分区是基于枚举出的值列表分区,range是基于给定的连续区间范围分区,
- hash分区:基于给定的分区个数和用户定义的表达式返回值来选择分区,该表达式对要插入到表的行中列值操作,HASH分区只能对整数进行分区,对于非整型字段只能通过表达式转为整型,MySQL支持两种HASH分区-常规hash和线性hash。
- key分区:类似于hash分区,但是HASH允许使用用户自定义表达式,而KEY分区不允许,它需要使用MySQL服务器提供的HASH函数,同时HASH分区只支持整数分区,而KEY分区支持除BLOB和TEXT类型外其他列;
无论哪种分区,要么你分区表上没有主键/唯一键,要么分区表的主键/唯一键都必须包含分区键,也就是说不能使用主键/唯一键字段之外的其它字段分区。
优点
- 和单个磁盘或者文件系统分区相比,可以存储更多数据,因为可以将分区表存储在不同物理磁盘上
- 对已过期或者不需要保存的数据,可以通过删除与这些数据有关的分区来快速删除数据,他的效率远比delete高;
- 在where子句中包含分区条件时,可以只扫描必要的一个或者多个分区来提高查询效率
- 同时在涉及sum()和count()这类聚合函数的查询时,可以容易的在每个分区上并行处理,最终只需要汇总所有分区得到的结果
- 跨多个磁盘来分散数据查询,获得更大的查询吞吐量。
分区和水平分表功能类似,将一个大表的数据分割到多张小表中去,由于查询不需要全表扫描了,只需要扫描某些分区,所以分区能提高查询速度。
- 水平分表需要用户预先手动显式创建出多张分表(如tbl_user0, tbl_user1, tbl_user2),在物理上实实在在的创建多张表,通过客户端代理(Sharding-JDBC等)或者中间件代理(Mycat等)来实现分表逻辑。
- 分区是MySQL的一个插件Plugin功能,将一张大表的数据在数据库底层分成多个分区文件(如tbl_user#P#p0.ibd, tbl_user#P#p1.ibd, tbl_user#P#p2.ibd),和水平分表不同的是分区不需要显式的创建“分表”,数据库会自动创建分区文件的,用户看到的只是一张普通的表,其实是对应的是多个分区,这个是对用户是屏蔽的、透明的,在使用上和使用一张表完全一样,不需要借助任何功能来实现。分区是一种逻辑上的水平分表,在物理层面还是一张表。
Hash分区主要用来分散热点读,确保数据在预先确定个数的分区中可能的平均分布。对一个表执行Hash分区时,mysql会对分区键应用一个散列函数,以此确定数据应当放在N个分区中的哪个分区。
mysql支持两种hash分区:
- 常规hash分区和线性hash分区(linear hash分区),常规hash分区使用的是取模算法,对应一个表达式expr是可以计算出它被保存到哪个分区中,N = MOD(expr, num)
- 线性hash分区使用的是一个线性的2的幂运算法则。