mysql分区之range分区

随着互联网的发展,各方面的数据越来越多,从最近两年大数据越来越强的呼声中就可见一斑。

我们所做的项目虽算不上什么大项目,但是由于业务量的问题,数据也是相当的多。

数据一多,就很容易出现性能问题,而为了解决这个问题我们通常很容易想到集群、分片等。

但是在某些时候却不一定必须要用集群、分片,也可以适当的使用数据分区。

什么是分区?

(以下引用自:http://wangweiak47.blog.51cto.com/2337362/1602422/

MySQL在未启用分区功能时,数据库的单个表内容是以单个文件的形式存放在文件系统上的。当启用分区功能后,MySQL将按用户指定的规则将单个表内容分割成几个文件存放在文件系统上。分区分为水平分区和垂直分区,水平分区是将表的数据按行分割成不同的数据文件,而垂直分区则是将表的数据按列分割成不同的数据文件。分片要遵循完备性原则、可重构性原则与不相交原则。完备性代表所有数据必须映射到某个片段上。可重构性表示所有分片数据必须可以重新构成全局数据。不相交性表示不同分片上的数据没有重复(除非你是特意做的冗余)。

大概是介于各方面的考虑,我们用的的表中就用到了range分区,数据库是其他人在管理,但是因为用到了这个表,因此我便抽时间进行了简单的学习。

据我的了解,要使用分区的话,必须要在创建表结构的时候就使用创建分区的语句,不能再后期更改。

例如我创建一个简单的emp表,有id、name、age三个字段,然后根据id分区。正确的建表语句基本如下:

CREATE TABLE emp(

id INT NOT NULL,

NAME VARCHAR(20),

age INT

)

PARTITION BY RANGE(ID)(

PARTITION p0 VALUES LESS THAN (6),

PARTITION p1 VALUES LESS THAN (11),

PARTITION pmax VALUES LESS THAN maxvalue

);

这里我是设置把整个表的数据分为三个区,id小于6的是一个区,区名称p0;id介于6到11的属于一个区,区名称p1;然后所有id大于11的一个区,区名称pmax。

整理一个语法,基本如下:

create table tablename(

字段名 数据类型

...

partition by range(分区依赖的字段名)(

partition 分取名 values less than (分区条件的值),

...

这里需要注意的是例子中的最后一行partition pmax values less than maxvalue,这一句中只有代表分区名的pmax是可以自己任意取得,剩下的单词不能变,maxvalue代表上边分区条件的最大值。

这样的话能保证所有数据都能正常入库,否则,假如没有这一句的话,那么id大于等于11的数据便无法存入库中,将会报错。

表结构创建好以后,为了测试分区是否成功,我向表中插入了一些数据,语句如下:

INSERT INTO emp VALUES(1,'test1',22);

INSERT INTO emp VALUES(2,'test2',25);

INSERT INTO emp VALUES(3,'test3',27);

INSERT INTO emp VALUES(4,'test4',20);

INSERT INTO emp VALUES(5,'test5',22);

INSERT INTO emp VALUES(6,'test6',25);

INSERT INTO emp VALUES(7,'test7',27);

INSERT INTO emp VALUES(8,'test8',20);

INSERT INTO emp VALUES(9,'test9',22);

INSERT INTO emp VALUES(10,'test10',25);

INSERT INTO emp VALUES(11,'test11',27);

INSERT INTO emp VALUES(12,'test12',20);

INSERT INTO emp VALUES(13,'test13',22);

INSERT INTO emp VALUES(14,'test14',25);

INSERT INTO emp VALUES(15,'test15',27);

INSERT INTO emp VALUES(16,'test16',20);

INSERT INTO emp VALUES(17,'test17',30);

INSERT INTO emp VALUES(18,'test18',40);

INSERT INTO emp VALUES(19,'test19',20);

数据插入完成后,要验证是否对应id的数据保存在了对应的分区,可以使用查询分区的命令,如下:

SELECT partition_name,partition_expression,partition_description,table_rows

FROM information_schema.PARTITIONS

WHERE table_schema = SCHEMA() AND table_name='emp'

查询出的结果如图:

可以看出partition_name是分区名,partition_expression是分区依赖的字段,partition_description可以理解成该分区的条件,table_rows表示该分区中现在有的数据量。

从上边的数据中可以看出分区是成功的,但是如上分区虽然可以避免无法插入的问题,却又出现了一个新的问题。

那就是最后一个pmax区的数据有可能非常的大,这样一来,数据并不平均,不成比例,有可能使得查询最后一个区的数据时依旧出现性能问题。所以,解决办法大致有这样三个:

一是在能控制分区字段数据的情况下,比如说这里的id,假如能明确的知道什么时候会是多大的值,那么就可以一开始的时候不要这个pmax,而是定期的增加分区。例如这里存在了p0、p1,那么可以在id即将到达11的时候增加p2、p3甚至更多。增加分区的语句示例如下:

ALTER TABLE emp ADD PARTITION(PARTITION p2 VALUES LESS THAN (16))

语法整理就是:alter table tablename add partition(partition 分区名 values lessthan (分区条件))

上边这个办法可以解决数据不成比例的这个问题,只不过也同时存在隐患,那就是假如什么时候忘了增加后边的分区,亦或者说是分区依赖的字段值超出了预料,那么就又可能导致数据无法入库的问题。这样一来又有两种方法可以解决:

一是可以使用mysql的事务机制和存储过程等,做一个mysql的定时任务,然后使数据库系统自己在特定的时间增加分区。这样一来基本上不会出现第一个方法所说的问题,只不过这种方法需要对mysql的事务和存储过程也有一定的理解,操作起来有一定的难度。

我知道这个方法,暂时还没有着手去实现,等后边进一步了解事务和存储过程后再给出相关的例子。

那么除开上边这种定时任务的方法外,还有一个就是拆分分区的办法,也就是还是使用之前有pmax分区的这个表结构,然后用拆分分区的语句来拆分pmax。示例如下:

ALTER TABLE emp REORGANIZE PARTITION pmax INTO(

PARTITION p2 VALUES LESS THAN (16),

PARTITION pmax VALUES LESS THAN maxvalue

)

然后我们再用查询分区情况的语句查询,便可以看到结果变成这样:

很显然,多出来了一个p2分区,拆分成功的同事不影响其他的功能。

那么这里分区拆分的语法整理如下:

alter table tablename reorganize partition 要拆分的分区名 into(

partition 拆分后的分区名1 values less than (条件),

partition 拆分后的分区名2 values lessthan (条件),

...

)

好了,到这里基本上算是完成了,但是我们知道数据库一般的操作都是增删改查,我们这里已经有了增改查,却自然也不能少了删。

按理说正常的生产环境的数据库应该是不能随意删除数据的,但是并不代表就不能删,反而有的时候还必须要删。

就比如我们项目中那个库,由于数据量太大,即便是分区了也依旧会在大量数据的情况下变慢。而与此同时,我们是按时间分区的,实际使用过程中只需要用到几天的数据,那么实际上很早以前的数据是可以删除不要的,或者说备份以后删除这个表的,这样就需要用到删除语句。

当然了,删除可以用delete,但是这样的话分区信息还在库中,实际上也是没必要要的,完全可以直接删除分区,因为删除分区的时候也同时会删除这个区内的所有数据。

示例之前我们先查一下之前插入的所有数据,如图:

这里示例删除p0分区代码如下:

ALTER TABLE emp DROP PARTITION p0

然后先用查询分区的代码看一下,如图

可以看到p0区不见了,在select * 一下,如图:

可以看到id小于6的数据已经没有了,数据删除成功。

时间: 2024-07-28 13:13:56

mysql分区之range分区的相关文章

mysql分区之RANGE分区讲解

  mysql分区之RANGE分区讲解 按照RANGE分区的表是通过如下一种方式进行分区的,每个分区包含那些分区表达式的值位于一个给定的连续区间内的行.这些区间要连续且不能相互重叠,使用VALUES LESS THAN操作符来进行定义.在下面的几个例子中,假定你创建了一个如下的一个表,该表保存有20家音像店的职员记录,这20家音像店的编号从1到20. CREATE TABLE employees ( id INT NOT NULL, fname VARCHAR(30), lname VARCHA

高性能的MySQL(7)分区技术详解

在我之前的2篇博客中已经简单介绍过MySQL5.1之后的分区技术的基本理论和分区技术的表存储文件及特点,博客地址如下: http://janephp.blog.51cto.com/4439680/1305220 http://janephp.blog.51cto.com/4439680/1305937 今天要介绍一下分区技术一些使用场景和机制. MySQL实现分区表的方式--对底层表封装--意味着索引也按照分区的子表定义的,而没有全局索引. 一.在下面的场景中,作用非常大: 1.表非常大无法全部

mysql分区之LIST分区讲解

  mysql分区之LIST分区讲解 MySQL中的LIST分区在很多方面类似于RANGE分区.和按照RANGE分区一样,每个分区必须明确定义.它们的主要区别在于,LIST分区中每个分区的定义和选择是基于某列的值从属于一个值列表集中的一个值,而RANGE分区是从属于一个连续区间值的集合.LIST分区通过使用"PARTITION BY LIST(expr)"来实现,其中"expr" 是某列值或一个基于某个列值.并返回一个整数值的表达式,然后通过"VALUES

range分区(实用篇)

上一篇blog对range分区做了个大概简介,接下来这篇对实际使用中的一些小细节进行分析总结.主要是新增和删除分区以及数据写入(null值的处理已在前面提到http://blog.sina.com.cn/s/blog_4d398f210100wrb8.html) ========================================================== 普通表: root@qw_test 01:49:44>show create table tmp_qw_test\G

mysql-为什么MySQL增加了partitions 分区后原来分区的table_rows就变了

问题描述 为什么MySQL增加了partitions 分区后原来分区的table_rows就变了 然后我插入了三条数据,现在tablerows为3 执行增加分区 然后,tablerows 变成2了 但是,我看数据库里面的数据没有变,请问这是怎么一回事?

mysql分表,分区的区别和联系

一,什么是MySQL分表,分区 什么是分表,从表面意思上看呢,就是把一张表分成N多个小表 什么是分区,分区呢就是把一张表的数据分成N多个区块,这些区块可以在同一个磁盘上,也可以在不同的磁盘上,具体请参考mysql分区功能详细介绍,以及实例 二,mysql分表和分区有什么区别呢 1,实现方式上 a),mysql的分表是真正的分表,一张表分成很多表后,每一个小表都是完正的一张表,都对应三个文件,一个.MYD数据文件,.MYI索引文件,.frm表结构文件. Java代码   [root@BlackGh

mysql分表和分区的区别浅析_Mysql

一.什么是mysql分表和分区 什么是分表,从表面意思上看呢,就是把一张表分成N多个小表 什么是分区,分区呢就是把一张表的数据分成N多个区块,这些区块可以在同一个磁盘上,也可以在不同的磁盘上 二.mysql分表和分区有什么区别呢 1.实现方式上 a)mysql的分表是真正的分表,一张表分成很多表后,每一个小表都是完正的一张表,都对应三个文件,一个.MYD数据文件,.MYI索引文件,.frm表结构文件. 复制代码 代码如下: [root@BlackGhost test]# ls |grep use

Oracle分区之四:分区维护和管理

一,分区表的相关实验 创建一个列表分区表 create table t3(id number,city varchar2(10)) partition by list(city) ( partition p1 values ('SH','JS','ZJ') , partition p2 values ('BJ','TJ','HB') , partition p3 values ('GZ','SZ') , partition p_others values (default) ); create

oracle 12c R1 在线迁移数据文件、在线迁移表分区或者子分区例子

在线重定义数据文件: 在oracle 12c R1之前的版本中,如果在线移动数据文件需要将表空间或者数据文件离线,然后操作系统mv,recover后online数据文件或者表空间,在oracle 12c R1后可以直接在线重定义数据文件,这个过程用户可以进行查询.DML以及DDL的任务,另外数据文件也可以直接在存储设备间迁移,比如ASM到文件系统的相互迁移. SQL> select name from v$datafile; NAME ------------------------------