(十)RANGE分区

---
title: 不懂SQL优化?那你就OUT了(十)

MySQL如何优化-- 分区(二)-- RANGE 分区

date: 2019-01-05

categories: 数据库优化
---

上篇博客我们讨论了分区的概述,优点和分区的类型。 这篇我们将更详细的讨论分区的类别:

###RANGE 分区

按范围分区的分区方式:每个分区 包含 分区表达式值位于给定范围内的行。范围应该是连续的,而不是重叠的,并且使用 <font style=‘color:coral‘>VALUES LESS THAN</font> 操作符来进行定义.

案列:

CREATE TABLE t_range_employee (
id INT NOT NULL, -- 员工编号
ename VARCHAR(30), -- 员工姓名
hired DATE NOT NULL DEFAULT ‘1970-01-01‘, -- 雇佣时间
separated DATE NOT NULL DEFAULT ‘9999-12-31‘, -- 离职时间
job_code INT NOT NULL, -- 职位编号
store_id INT NOT NULL -- 所在音像店编号
)ENGINE=INNODB ;

> 注意:
>
> 这里使用的t_range_employee表<span style=‘color:coral;font-size:20px;‘>没有主键或惟一键</span>。
>
> 你应该记住,极有可能在实践中表是有主键,唯一键,或两者兼而有之,这使得在 选择分区列 时要取决于这些列是否有主键和唯一键, 如果有主键或则唯一键时,我们将在后面 关于分区的限制中讨论(分区键、主键和惟一键)

根据你的需要,这个表可以有多种方式来按照范围区间进行分区。

一种分区方案是使用store_id列进行分区。例如,可以通过添加一个<span style=‘color:coral;font-size:15px;‘>partition by RANGE子句</span>把这个表分割成4个区间,如下所示:

CREATE TABLE t_range_employee (
id INT NOT NULL, -- 员工编号
ename VARCHAR(30), -- 员工姓名
hired DATE NOT NULL DEFAULT ‘1970-01-01‘, -- 雇佣时间
separated DATE NOT NULL DEFAULT ‘9999-12-31‘, -- 离职时间
job_code INT NOT NULL, -- 职位编号
store_id INT NOT NULL -- 所在音像店编号
) ENGINE=INNODB
PARTITION BY RANGE (store_id) (
PARTITION p0 VALUES LESS THAN (6),
PARTITION p1 VALUES LESS THAN (11),
PARTITION p2 VALUES LESS THAN (16),
PARTITION p3 VALUES LESS THAN (21)
);

在这个范围分区方案中,存储的音像店编号为 1到5 的员工对应的所有行 存储在分区p0中,存储音像店编号6到10的员工对应的行存储在分区p1中,以此类推。每个分区都是按照从低到高的顺序定义的。这是按范围语法划分的要求; 你可以把范围分区想象成C和JAVA语言中的if...elseif…语句

如果往表中添加一条数据:

INSERT INTO t_range_employee VALUES(18,‘张某某‘,‘2008-11-02‘,DEFAULT,1,15);

此时很容易确定将这条新数据插入到分区p2中。 那么找查找这条数据时,mysql就会只在p2分区快中查找,这样效率就会快很多。

但是此时有个问题 ?如果此时往音像店表中添加第21家商店时,会发生什么呢?

由于t_range_employee表没有放置store_id大于20的行的分区,因此会出现错误,因为服务器不知道将其放置在何处。要避免这种错误,你可以通过在 CREATE TABLE 语句中使用 一个 “catchall” VALUES LESS THAN子句,该子句提供了将所有大于指定最大值的行放置该分区中。

例如:

CREATE TABLE t_range_employee (
id INT NOT NULL, -- 员工编号
ename VARCHAR(30), -- 员工姓名
hired DATE NOT NULL DEFAULT ‘1970-01-01‘, -- 雇佣时间
separated DATE NOT NULL DEFAULT ‘9999-12-31‘, -- 离职时间
job_code INT NOT NULL, -- 职位编号
store_id INT NOT NULL -- 所在音像店编号
) ENGINE=INNODB
PARTITION BY RANGE (store_id) (
PARTITION p0 VALUES LESS THAN (6),
PARTITION p1 VALUES LESS THAN (11),
PARTITION p2 VALUES LESS THAN (16),
PARTITION p3 VALUES LESS THAN (21),
PARTITION p4 VALUES LESS THAN MAXVALUE
);

MAXVALUE 表示的整数值总是大于可能的最大整数值(在数学中,它是最小上界)。也就是说,当store_id 列值大于或等于21(定义的最大值)的任何行都存储在p4分区中,在将来的某个时候,当存储的数量增加到25、30或更多时,您可以使用ALTER TABLE语句为存储21-25、26-30等添加新的分区(有关如何做到这一点的详细信息,将会在后面的分区管理中讨论”)。

以同样的方式,你也可以使用 job_code 来进行分区,假设两位数的编号用于普通(店内)员工,三位数编号的用于办公室和技术支持人员,四位数编号用于管理职位,您可以使用以下语句创建分区表:

CREATE TABLE t_range_employee (
id INT NOT NULL, -- 员工编号
ename VARCHAR(30), -- 员工姓名
hired DATE NOT NULL DEFAULT ‘1970-01-01‘, -- 雇佣时间
separated DATE NOT NULL DEFAULT ‘9999-12-31‘, -- 离职时间
job_code INT NOT NULL, -- 职位编号
store_id INT NOT NULL -- 所在音像店编号
) ENGINE=INNODB
PARTITION BY RANGE (job_code) (
PARTITION p0 VALUES LESS THAN (100),
PARTITION p1 VALUES LESS THAN (1000),
PARTITION p2 VALUES LESS THAN (10000)

);

当然您也可以在分区子句中使用表达式。但是,MySQL必须能够计算表达式的值,并且返回值作为小于(<)比较的一部分。

例如: 使用雇佣时间来分区,把雇佣时间在2000年之前的划分到p0区,2000到2015年的划分到p1区,2015年--2020年放到p2区,其他年份的放到p3区

CREATE TABLE t_range_employee (
id INT NOT NULL, -- 员工编号
ename VARCHAR(30), -- 员工姓名
hired DATE NOT NULL DEFAULT ‘1970-01-01‘, -- 雇佣时间
separated DATE NOT NULL DEFAULT ‘9999-12-31‘, -- 离职时间
job_code INT NOT NULL, -- 职位编号
store_id INT NOT NULL -- 所在音像店编号
) ENGINE=INNODB
PARTITION BY RANGE (YEAR(hired)) (
PARTITION p0 VALUES LESS THAN (2000),
PARTITION p1 VALUES LESS THAN (2015),
PARTITION p2 VALUES LESS THAN (2020),
PARTITION p3 VALUES LESS THAN MAXVALUE
);

####什么时候使用范围分区

RANGE分区在如下场合特别有用:

1. 需要删除一些旧数据的时候。

如果你使用的是按雇佣时间来分区的方案,那么您可以简单地使用 alter table t_range_employee drop partition p0 来删除 雇佣分年在2000以前的数据。这比你执行 delete from t_range_employee where year(hired) <2000 语句的效率高很多。

2. 想要使用一个包含有日期或时间值,或包含有从一些其他级数开始增长的值的列。

3. 经常运行直接依赖于用于分割表的列的查询。

例如: 当你需要执行:
EXPLAIN SELECT COUNT(*) FROM t_range_employee WHERE separated BETWEEN ‘2000-01-01‘ AND ‘2000-12-31‘ GROUP BY store_id; MySQL可以快速确定只需要扫描分区p1,因为其余的分区不能包含任何满足WHERE子句的记录。

原文地址:https://www.cnblogs.com/ysviewvicn/p/10288367.html

时间: 2024-10-20 13:04:18

(十)RANGE分区的相关文章

oracle interval-partition 解决range分区大难题

博客<oracle分区>中讲了oracle的几种分区,并且对于oracle的典型分区如Range分区和List分区给了示例. 在实际运用Range分区时,遇到了这样的难题: createtableTMP_LXQ_1 ( PROPOSALNO             VARCHAR2(22), STARTDATE              DATE ) partitionbyrange(STARTDATE) ( partitionpart_t01values less than(to_date(

MySQL数据表range分区例子

某些行业数据量的增长速度极快,随着数据库中数据量的急速膨胀,数据库的插入和查询效率越来越低.此时,除了程序代码和查询语句外,还得在数据库的结构上做点更改:在一个主读辅写的数据库中,当数据表数据超过1000w行后,那查询效率真的很让人抓狂.就算早前建了索引,也很难满足用户对于系统查询效率的体验. 优化方案是分表或分区.至于分区的原理以及分区和分表的区别,搜索一下,都介绍的很详细,这里就不作冗余介绍.简单来讲,分表旨在提高数据库的并发能力,分区旨在优化磁盘的IO和数据的读写,所以采用什么方案,还得根

【oracle】分区表:range分区,list分区,hash分区

 ************************************************************************   ****原文:blog.csdn.net/clark_xu 徐长亮的专栏 ************************************************************************ --(1)分区表包含多个分区,每个分区都是在一个独立的segment上面,可以存放不同的表空间: --(1.1)官方推荐超过

MySQL range分区(二)

MySQL range分区使用最多:具体介绍请看一 例子:该例子为本人个人学习总结分享->详细说明-->有问题欢迎前来交流 MySQL range分区(二)

Mysql 分区介绍(二) —— RANGE分区

通过范围的方式进行分区, 为每个分区给出一定的范围, 范围必须是连续的并且不能重复, 使用VALUES LESS THAN操作符<br /> 让我们先来创建一个range分区的表 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

MySql采用range分区可提升查询效率

简介: RANGE分区基于一个给定的连续区间范围,早期版本RANGE主要是基于整数的分区.在5.7版本中DATE.DATETIME列也可以使用RANGE分区,同时在5.5以上的版本提供了基于非整形的RANGE COLUMN分区.RANGE分区必须的连续的且不能重叠.使用 "VALUES LESS THAN ()" 来定义分区区间,非整形的范围值需要使用单引号,并且可以使用MAXVALUE作为分区的最高值. 本文将给大家介绍MySQL 5.6.24 range分区增加删除处理的相关内容,

MySQL5.5 RANGE分区增加删除处理

一.删除分区 ##查看要处理的分区的数据量,并导出作为备份 mysql> select count(*)  from baby_account_change_log where updated_time >'2016-12-01 00:00:00' and updated_time <'2017-01-01 00:00:00'; +----------+ | count(*) | +----------+ |    66252 | +----------+ 1 row in set (0

十四、mysql 分区之 HASH &amp;&amp; KEY

1.hash分区 PS::个人觉得HASH分区很好很强大,简单确分布极其均匀 创建实例: CREATE TABLE HASH_EMP ( tid int, tname char(255) ) PARTITION BY HASH (tid) PARTITIONS 8; 将hash_emp进行的tid进行hash分区,并分为8个区 查询分区的数据分布情况: select partition_name,partition_expression,partition_description,table_r

十五、mysql 分区之 分区管理

1.mysql分区处理分区字段NULL值的方式 1.range分区null被当作最小值处理 2.list分区null值必须被枚举出来,否则将出错 3.hash/key分区 null值当作0处理 2.RANGE && LIST 分区管理 1.删除分区 alter table emp drop partition p0; //删除emp的p0分区,注意也会同时删除该分区的数据 2.增加分区 alter table emp add partition (partition p5 values l