简介

分区是指根据一定的规则,数据库把一个表分解成多个更小的、更容易管理的部分。

就访问数据库的应用而言,逻辑上只有一个表或一个索引,但是实际上这个表可能由数 10 个物理分区对象组成,每个分区都是一个独立的对象,从局部来说,每个分区别可以独自处理任务,从整体来说,每个分区表可以作为总表的一部分进行处理。分区对应用来说是完全透明的,不影响应用的业务逻辑。

分区表的底层存储结构

从上面的说明我们可以看到,分区表是一个独立的逻辑表,但是底层由多个物理子表组成。实现分区的代码实际上是对一组底层表的的封装。对分区表的请求,都会转化成对存储引擎的接口调用。所以为了支持分区的概念,SQL服务端做了很多的处理,将分区的操作进行了内部封装,对使用者是透明的(也就是用户照常写sql就行了),但是如果我们从底层的文件系统来看就会发现,每一个分区表都有一个使用#分隔命名的表文件。

分区表的底层操作逻辑与原理

逻辑

select

当查询一个分区表的时候,分区层先打开并锁定住所有的底层表。优化器先判断是否可以过滤部分分区,然后在调用对应的存储引擎接口访问各个分区的数据。

insert

当写入一条记录时,分区层先打开并锁住所有的底层表,然后确定那个分区接收者条记录,在将记录写入对应底层表。

delete

当删除一条记录时,分区层先打开并锁住所有的底层表,然后确定数据对应的分区,最后对响应底层表进行删除操作。

update(先增后删)

当更新一条记录时,分区层先打开并锁住所有的底层表,MySQL先确定需要更新的记录在哪个分区,然后取出数据并更新,再判断更新后的数据应该放在哪个分区,最后对底层表进行写入操作,并对原数据所在的底层表进行删除操作。

原理

如前所述,分区表由多个相关的底层表实现,这些底层表也是由句柄对象 (Handlerobject)表示,所以我们也可以直接访问各个分区。存储引擎管理分区的各个底层表和管理普通表一样(所有的底层表都必须使用相同的存储引擎),分区表的索引只是在各个底层表上各自加上一个完全相同的索引。

从存储引擎的角度来看,底层表和一个普通表没有任何不同(分区表无非就是分区器对一张表进行了二次拆分),存储引擎也无须知道这是一个普通表还是一个分区表的一部分。分区表上的操作按照下面的操作逻辑进行: 虽然每个操作都会“先打开并锁住所有的底层表”,但这并不是说分区表 在处理过程中是锁住全表的。

如果存储引擎能够自己实现行级锁,例如 InnoDB,则会在分区层释放对应表锁。这个加锁和解锁过程与普通 InnoDB 上的查询类似。

分区表的好处

快速查找

MySQL 在创建表时使用 PARTITION BY 子句定义每个分区存放的数据。在执行查询的时候,优化器会根据分区定义过滤那些没有我们需要数据的分区,这样查询就无须扫描所有分区,只需要查找包含需要数据的分区就可以了。

快速删除

分区的一个主要目的是将数据按照一个较粗的粒度分在不同的表中。这样做可以将相关的数据存放在一起,另外,如果想一次批量删除整个分区的数据也会变得很方便。在下面的场景中,分区可以起到非常大的作用。

与ConcurrentHashMap的对比

不难发现,与ConcurrentHashMap的设计思路类似,都是为了减小锁粒度而实现的。

分区表的使用场景

  1. 表非常大以至于无法全部都放在内存中,或者只在表的最后部分有热点数据,其他均是历史数据。
  2. 分区表的数据更容易维护。例如,想批量删除大量数据可以使用清除整 个分区的方式。另外,还可以对一个独立分区进行优化、检查、修复等操作。
  3. 分区表的数据可以分布在不同的物理设备上,从而高效地利用多个硬件设备。可以使用分区表来避免某些特殊的瓶颈,例如 InnoDB 的单个索 引的互斥访问、ext3 文件系统的 inode 锁竞争等。

注意:这里指的硬件设备并不是不同的服务器,而是同一个服务器的不同硬盘。

这里可以指定存储磁盘路径。因此可以放到不同的磁盘中。

  1. 如果需要,还可以备份和恢复独立的分区,这在非常大的数据集的场景下效果非常好。

分区表的部分限制

  1. 一个表最多只能有 1024 个分区。
  2. 如果主键和唯一索引是多个列组成的联合索引,那么分区字段就必须包含这个联合索引所有的列。比如:
create table rcx (
a int,
b int,
c char(3)
)engine=innodb
partition by range columns(a,b,c) (
partition p0 values
);
  1. 分区表中无法使用外键约束。

分区表的类型

RANGE(范围离散值)分区

创建分区

行数据基于属于一个给定连续区间的列值被放入分区。

create table t(
id int
)engine=innodb
partition by range (id) (
partition p0 values less than (10),
partition p1 values less than (20)
);

查看表在磁盘上的物理文件,启用分区之后,表不再由一个ibd文件组成了,而是由建立分区时的各个分区ibd文件组成如t#p#p0.ibd、t#p#p1.ibd。

插入数据

insert into t values(1);
insert into t values(9);
insert into t values(10);
insert into t values(15);

可以通过查询information_schema数据库中的partitions表来查看每个分区的具体信息:

select * from information_schema.partitions
where table_schema='test_partition'and table_name='t'\G;

对于表t,由于定义了分区,因此对于插入的值应该严格遵守分区的定义,当插入一个不在分区中定义的值时,MySQL数据库会抛出了一个异常。

为解决上述问题,可以对分区添加一个MAXVALUE值的分区,MAXVALUE可以理解为正无穷,让我们的分区表更加的健壮:

alter table t add partition(partition p2 values less than maxvalue);

查询数据

使用explain查看SQL语句的执行计划:

explain
select * from t
where id<10 and id>0\G;

可以看到经过分区器过滤后,仅仅会对p0分区进行查询。缩小查询范围。

List(指定离散值)分区

LIST分区和RANGE分区非常相似,只是分区列的值是离散的。

创建分区

create table r (
a int,
b int)engine=innodb
partition by list (b) (
partition p0 values in (1,3,5,7,9),
partition p1 values in (0,2,4,6,8));

插入数据

insert into r select 1,1;
insert into r select 1,2;
insert into r select 1,3;
insert into r select 1,4;

查询数据

select table_name,partition_name,table_rows
from information_schema.partitions
where table_name='r' and table_schema='test_partition'\G;

HASH(散列)分区

HASH分区的目的是将数据均匀地分布到预先定义的各个分区中,保证各分区的数据量大致都是一样的。

在RANGE分区和LIST分区中,必须明确指定一个给定的列值或列值集合应该保存在哪个分区中;而在HASH分区中,MySQL自动完成这些工作,用户要做的只是基于将要进行的哈希分区的列值指定一个列值或表达式,以及指定被分区的表将要被分割成的分区数量。

创建HASH分区

create table t_hash(
a int,
b datetime
)engine=innodb
partition by hash (year(b))
partitions 4;//四个分区

插入数据

 insert into t_hash values(1,'2010-04-01');

分区算法如下

MOD(YEAR('2010-04-01'),4)
=MOD(2010,4)
=2

查看分区情况

select table_name,partition_name,table_rows
from information_schema.partitions
where table_name='t_hash' and table_schema='test_partition'\G;

创建LINEAR HASH分区

MySQL还支持一种称为LINEAR HASH的分区,它使用一个更复杂的算法来确定新行插入到已分区的表中的位置。它的语法和HASH分区的语法相似,只是将HASH改为LINEAR HASH。

create table t_l_hash(
a int,
b datetime
)engine=innodb
partition by linear hash (year(b))
partitions 4;

插入一条记录

insert into t_l_hash values(1,'2010-04-01');

分区判断

  • 取大于分区数量4的下一个2的幂值V,V=POWER(2,CEILING(LOG(2,num)))=4
  • 所在分区N=YEAR(‘2010-04-01’)&(V-1)=2

LINEAR HASH优劣分析

LINEAR HASH分区的优点在于,增加、删除、合并和拆分分区将变得更加快捷,这有利于处理含有大量数据的表。它的缺点在于,与使用HASH分区得到的数据分布相比,各个分区间数据可能不大均衡。

KEY(默认算法)分区

KEY分区和HASH分区相似,不同之处在于HASH分区使用用户定义的函数进行分区,KEY分区使用MySQL提供的函数进行分区。

create table t_key (
a int,
b datetime
)engine=innodb
partition by key(b)
partitions 4;

COLUMNS分区

前面介绍的RANGE、LIST、HASH和KEY这四种分区中,分区的条件是:数据必须是整型,如果不是整型,那应该需要通过函数将其转换为整型,如year()等函数。COLUMNS分区可以直接使用非整型的数据进行分区,分区根据类型直接比较而得,不需要转换为整型。此外RANGE COLUMNS分区可以对多个列的值进行分区。

COLUMNS分区支持以下的数据类型:

range columns时间分区

create table t_columns(
a int,
b datetime
)engine=innodb
partition by range columns (b) (
partition p0 values less than ('2009-01-01'),
partition p1 values less than ('2010-01-01')
);

list columns指定字段分区

create table t_columns2(
a int,
b datetime,
city varchar(15)
)engine=innodb
partition by list columns(city) (
partition p1 values in ('a','b','c'),
partition p2 values in ('d','e','f'),
partition p3 values in ('g','h','k'),
);

range columns多列分区

create table rcx (
a int,
b int,
c char(3)
)engine=innodb
partition by range columns(a,b,c) (
partition p0 values
);

子分区

子分区是在分区的基础上再进行分区,也叫复合分区。MySQL允许在RANGE和LIST的分区上再进行HASH或KEY的子分区。

在上面的例子中,我们看见 range 和 List 都是整数类型分区,其实 range 和 List 也支持非整数分区,但是要结合COLUMN 分区,支持整形、日期、字符串。

指定子分区数量分区

create table ts (a int,b date)engine=innodb
partition by range(year(b))
subpartition by hash(to_days(b))
subpartitions 2 (
partition p0 values less than (1990),
partition p1 values less than (2000),
partition p2 values less than MAXVALUE)

可以看到,上面的分区规则相当于先用range分成两个区域,再用hash对每个range分成了三个区域。因此应该有2*3=6个分区区域。

指定子分区名分区

我们也可以通过使用subpartition语法来显式地指出各个子分区的名字

create table ts(
a int,
b date
)engine=innodb
partition by range(year(b))
subpartition by hash(to_days(b)) (
partition p0 values less than (1990) (
subpartition s0,
subpartition s1
),
partition p1 values less than (2000) (
subpartition s2,
subpartition s3
),
partition p0 values less than MAXVALUE (
subpartition s4,
subpartition s5
));

子分区注意事项

  • 每个子分区的数量必须相同
  • 要在一个分区表的任何分区上使用subpartition来明确定义任何子分区,就必须定义所有子分区。
  • 每个subpartition子句必须包括子分区的一个名字。
  • 子分区的名字必须是唯一的。

不建议使用mysql分区表

讲了这么多分区表,最后你跟我说不建议使用分区表???

因为在实际开发中,我们往往使用的是分库分表。分库分表除了支持MySQL分区表的水平切分(拆分行)以外,还支持垂直切分(拆分列)。把一个很大的库(表)的数据分到几个库(表)中。每个库(表)的结构都相同。但他们可能分布在不同的mysql实例,甚至不同的物理机上,以达到降低单库(表)数据量,提高访问性能的目的。

两者对比起来

  1. 分区表,分区键设计不太灵活,如果不走分区键,很容易出现全表锁
  2. 一旦数据量并发量上来,如果在分区表实施关联,就是一个灾难
  3. 自己分库分表,自己掌控业务场景与访问模式,可控。分区表,研发写了一个 sql,都不确定 mysql 底层的分区逻辑是怎样的,不太可控。
  4. 分区表无论怎么分,都是在一台机器上,天然就有性能的上限

什么是MySQL分区表相关推荐

  1. mysql 分区表 归档_MySQL分区表

    1,MySQL分区表作用 当单表的数据量较大,需要进行定期的数据归档删除时,或者提高查询性能,都可以采用分区: 2,分区表设置 分区的种类 range分区 list分区 hash分区 key分区 ra ...

  2. 数据切分——Mysql分区表的管理与维护

    关于Mysql分区表的介绍可以参考: http://blog.csdn.net/jhq0113/article/details/44592865 关于Mysql分区表的创建可以参考: http://b ...

  3. Mysql分区表的使用

    简单来说,分区表就是把物理表结构相同的几张表,通过一定算法,组成一张逻辑大表.这种算法叫"分区函数",当前 MySQL 数据库支持的分区函数类型有 RANGE.LIST.HASH. ...

  4. 数据切分——Mysql分区表的建立及性能分析

    Mysql的安装方法可以参考: http://blog.csdn.net/jhq0113/article/details/43812895 Mysql分区表的介绍可以参考: http://blog.c ...

  5. 简述MySQL分区表类型

    分区是将一个表的数据按照某种方式,比如按照时间上的月份,分成多个较小的,更容易管理的部分,但是逻辑上仍是一个表.我们在此之前已经讲过MySQL分区表的原理,分区有利于管理非常大的表,它采用分而治之的逻 ...

  6. Mysql分区表概述、分区类型、分区管理

    另有一篇简单易懂的好文章帮助学习 Mysql分区表的原理和优缺点以及注意点 一.分区概述 分区是指根据一定的规则,数据库把一个表分解成多个更小的.更容易管理的部分.分区有利于管理非常大的表. MySQ ...

  7. mysql表分区数量限制_详解MySQL分区表的局限和限制的代码实例

    本文对Mysql分区表的局限性做了一些总结,因为个人能力以及测试环境的 原因,有可能有错误的地方,还请大家看到能及时指出,当然有兴趣的朋友可以去官方网站查阅. 禁止构建 分区表达式不支持以下几种构建: ...

  8. mysql表分区备份_ZRM 2.1:备份MySQL分区表

    ZRM 2.1:备份MySQL分区表 MySQL 5.1通常可供生产使用. MySQL 5.1的主要功能之一就是分区. 表分区可以帮助提高性能和可用性. 表可以根据范围(给定范围内的列值),列表(匹配 ...

  9. 如何创建mysql分区表_mysql分区表创建思路

    mysql分区表有range,list,hash,key,其中每个分区又有特殊的类型.对于RANGE分区,有RANGE COLUMNS分区.对于LIST分区,有LIST COLUMNS分区.对于HAS ...

  10. mysql分区表truncate分区数据_详解MySQL分区表

    前言: 分区是一种表的设计模式,通俗地讲表分区是将一大表,根据条件分割成若干个小表.但是对于应用程序来讲,分区的表和没有分区的表是一样的.换句话来讲,分区对于应用是透明的,只是数据库对于数据的重新整理 ...

最新文章

  1. Spring 注解之@RestController与@Controller的区别
  2. 一个简单XSS攻击示例及处理
  3. 素数分布 - nefu 117
  4. 德利捷读码器设置软件_S7-1500PLC+变频器+编码器组成位置控制系统
  5. golang mysql 超时_Go语言channel超时机制
  6. NODE安装N管理出错
  7. 《SQL高级应用和数据仓库基础(MySQL版)》学习笔记 ·006【事务】
  8. 服务器硬件 做raid操作 ubuntu linux做raid
  9. 【颅内出血识别问题】数据分析与可视化
  10. 2012年5月16日,Google发布“知识图谱(Knowledge Graph)”
  11. 托业词汇汇总(修订版)
  12. 算法入门到进阶(一)——算法复杂度
  13. 云计算虚拟化技术和容器技术
  14. 由自身经历谈“不谋全局者,不足以谋一域”
  15. 脸书COO桑德伯格:最终塑造我们的,是我们经历的艰难时光
  16. 数据可视化之excel和finebi报表实现对比
  17. 朴素贝叶斯的应用_TF-IDF实例
  18. MySQL创建/查看/修改/删除数据库
  19. 计算机理论导引 期末,计算机理论导引实验报告_CFG是P成员
  20. 前端面试题(AJAX)

热门文章

  1. 用Python预测某某国际平台概率分析(一):这个到底是什么,是什么样的规则?...
  2. 评分卡模型开发-定量指标筛选
  3. webpack devtool浅析
  4. 人机交互-4-评估之观察用户
  5. Python 调用 MessageBeep 播放系统音效
  6. 在 CSS 中设置 cellpadding 和 cellspacing?
  7. java 图片上传 并保存服务器本地 后台 代码
  8. 打工人,别着急摆烂,看看你到底值多少钱?
  9. 我的计算机学习过程与.net学习过程(一):大学之前(转)
  10. mysql 中 ROW_FORMAT的选择