MYSQL优化_MYSQL分区技术[转载]
MySQL分区技术是用来减轻海量数据带来的负担,解决数据库性能下降问题的一种方式,其他的方式还有建立索引,大表拆小表等等。
MySQL分区按照分区的参考方式来分有RANGE分区、LIST分区、HASH分区、KEY分区。本文对这几种分区方式进行了详细的介绍,并且给出了简单的示例,文章简洁明了,对于想要初步了解MySQL分区技术的同学来说是很不错的参考材料。
一、背景介绍
当 MySQL中一个表的总记录数超过了1000万,会出现性能的大幅度下降吗?答案是肯定的。但性能下降的比率由系统的架构、应用程序、数据库索引、服务器硬件等多种因素而定。数据库多达上亿的数据量,分表之后的单个表也已经突破千万,那么单个表的更新等均影响着系统的运行效率。甚至是一条简单的SQL都有可能压垮整个数据库,如整个表对某个字段的排序操作等。
目前,针对海量数据的优化主要有2种方法:大表拆小表的方式、SQL语句的优化。
SQL语句的优化:可以通过增加索引等来调整,但是数据量的增大将会导致索引的维护代价增大。在此不详述,建议大家参考相应的《High Performance MySQL》等书籍。
大表拆小表的方式主要有两种:
1,垂直分表:

图1,垂直分区示意图
对于垂直分表,它将一个N1+N2个字段的表Tab拆分成N1字段的子表Tab1和(N2+1)字段的子表Tab2;其中子表Tab2包含了关于子表Tab1的主键信息,否则两个表的关联关系就会丢失。当然垂直分表会带来程序端SQL的修改,若是应用程序已经应用很长的一段时间,然后程序的升级将是耗时而且易出错的,即升级的代价将会很大。
2,水平分表:

图2,水平分区示意图
水平分区技术将一个表拆成多个表,比较常用的方式是将表中的记录按照某种Hash算法进行拆分,简单的拆分方法如取模方式。同样,这种分区方法也必须对前端的应用程序中的SQL进行修改方可使用。而且对于一个SQL,它可能会修改两个表,那么你必须得写成2个SQL语句从而可以完成一个逻辑的事务,使得程序的判断逻辑越来越复杂,这样也会导致程序的维护代价高,也就失去了采用数据库的优势。因此,分区技术可以有力地避免如上的弊端,成为解决海量数据存储的有力方法。
二、MySQL分区介绍
MySQL的分区技术不同与之前的分表技术,它与水平分表有点类似,但是它是在逻辑层进行的水平分表,对与应用程序而言它还是一张表。MySQL5.1有5种分区类型:
RANGE分区:基于属于一个给定连续区间的列值,把多行分配给分区;
LIST分区:类似于按RANGE分区,区别在于LIST分区是基于列值匹配一个离散值集合中的某个值来进行选择;
HASH分区:基于用户定义的表达式的返回值来进行选择的分区,该表达式使用将要插入到表中的这些行的列值进行计算。这个函数可以包含MySQL中有效的、产生非负整数值的任何表达式;
KEY分区:类似于按HASH分区,区别在于KEY分区只支持计算一列或多列,且MySQL服务器提供其自身的哈希函数。
1,RANGE分区
对于RANGE分区,举个例子:
例1:假定你创建了一个如下的表,该表保存有20家音像店的职员记录,这20家音像店的编号从1到20。如果你想将其分成4个小分区,那么你可以采用RANGE分区,创建的数据库表如下:

图3,RANGE分区实例1
在这个例子,key是一个整型的数据,那是否对于其它类型的字段就无法作为key呢?答案是否定的,例子2说明这种情况。
例2:假定你创建了一个如下的表,该表保存有20家音像店的职员记录,这20家音像店的编号从1到20。你想把不同时期离职的员工进行分别存储,那么你可以将日期字段separated(即离职时间)作为一个key,创建的SQL语句如下:

图4,RANGE分区实例2
这样你就可以对一个日期类型的字段调用mysql的日期函数YEAR()转换为一种整数类型,从而可以作为RANGE分区的key。这个时候你可以看到,分区后的物理文件是相对独立的:

图5,RANGE分区后物理文件
可知,每个分区有自己独立的数据文件和索引文件,这是为什么你对某一个查询,它只会访问它需要访问的数据块,而不访问根本不是结果的物理块,从而可以大大提高系统的效率。
2,LIST分区
LIST分区与RANGE分区有类似的地方,举个与例1类似的例子如下:
例3:假定你创建了一个如下的一个表,该表保存有20家音像店的职员记录,这20家音像店的编号从1到20。而这20个音像店,分布在4个有经销权的地区,如下表所示:

图6,LIST分区实例3
那么你可以采用如下的LIST分区语句创建数据表:

图7,LIST分区实例SQL语句
同样,它在物理文件上也会标识不同的分区:

图8,LIST分区后物理文件
3,HASH分区
HASH分区主要用来确保数据在预先确定数目的分区中平均分布。它可以基于用户定义的表达式的返回值来进行选择的分区,该表达式使用将要插入到表中的这些行的列值进行计算。
例4:假定你创建了一个如下的一个表,该表保存有20家音像店的职员记录,这20家音像店的编号从1到20。你想把不同时期加入的员工进行分别存储,那么你可以将日期字段hired(即离职时间)作为一个key,创建的SQL语句如下:

图9,HASH分区实例4
那么要插入一个在2005-09-15日入职的员工E1,那么按照取模函数会将其放置到第2分区中:
MOD(YEAR(‘2005-09-01’), 4)= MOD(2005,4)= 1 //即第2分区
4,KEY分区
与HASH分区类似,但它的key可以不是整数类型,如字符串等类型的字段。MySQL 簇(Cluster)使用函数MD5()来实现KEY分区;对于使用其他存储引擎的表,服务器使用其自己内部的哈希函数,这些函数是基于与PASSWORD()一样的运算法则。
5,不同分区技术的对比
如上分别列出了不同的分区技术,接下来进行对比,如下表所示:

图10,不同分区技术对比
三、案例分析
这个案例是针对有个员工、部门、部门经理、头衔和销售记录的模拟数据,其ER图如下所示,数据量大概有4百万左右。数据下载URL:https://launchpad.net/test-db

图11,案例分析
通过如上可知,对于同样的数据按照分区和不分区的技术分别存储,从而便于如下的查询性能分析和对比。对于salaries表,它采用RANGE分区,定义如下:

图12,案例分析
1,单表查询
从销售记录中找到1999年整年的销售记录有多少条,这个很简单,查询语句如下:
select count(*) from salaries s where s.from_date between"1999-01-01" and "1999-12-31" ;
那么对于分区前后的查询性能却有很大的差别:

图13,分区前后查询性能对比
通过如上可知,利用分区之后它只需扫描p16分区,访问的记录明显减少,所以性能自然有较大的提升:

图14,无采用分区技术和采用分区技术性能对比
2,单表查询的badcase
若现在有如下查询:
select count(*) from salaries s where year(s.from_date)=1999;
那么它是否能够利用到分区技术呢,答案是否定的。为什么呢,因为分区中的key是s.from_date,而不是year(s.from_date),mysql并不能很智能地判断year是1999的,那么它就是分为p16分区,这个可以通过如下的查询计划可以证实:

图15,未优化前的单表查询
也就是其实它访问了所有的分区,所以并没有很好地利用分区功能,将SQL改写如下:
select count(*) from salaries s where year between '1999-01-01' and'1999-12-31' ;
则查询计划如下:

图16,改进后的单表查询
可知,书写正确的SQL可以完全表现出两种相差特别大的性能。
3,连接查询
同样地,对于连接查询,在有没有分区的条件下,将有性能3倍左右的差距。对于更大的数据量,可能会有更大的性能差距。SQL如下:
select count(*) from salaries s left join employees e ons.emp_no=e.emp_no where s.from_date between '1999-01-01' and '1999-12-31' ;

图17,无采用分区和采用分区的性能对比
4,删除查询
为了删除1998年的销售数据,那么在有分区情况下可以不利用delete查询快速地完成垃圾数据的清理。

图18,删除查询性能对比
可知,对于有分区的情况下,只需要将某个分区删除掉即可,时间仅为0.05s,相对应原来的2.82s,这个提升是非常高的。当然,利用分区功能删除之后的数据文件信息如下:

图19,利用分区功能删除后的文件信息
那么接下来如果接着插入1998年的数据,数据是否丢失了呢?还是会写不进去?答案也都是否定,它会将数据写入p16分区中。有兴趣的读者可以自己收到试试。
四、总结和不足
分区的好处有很多:
1,与单个磁盘或文件系统分区相比,可以存储更多的数据;
2,对于那些已经失去保存意义的数据,通常可以通过删除与那些数据有关的分区,很容易地删除那些数据;
3,一些查询可以得到极大的优化,如where语句数据可以只保存在一个或多个分区内;
4,涉及到例如SUM()和COUNT()这样聚合函数的查询,可以很容易地进行并行处理;
5,通过跨多个磁盘来分散数据查询,来获得更大的查询吞吐量。
在设计分区过程中,需要考虑的因素有很多,如:
1,分区的列;
2,分区使用的函数,特别是非Integer类型的列;
3,服务器性能;
4,内存大小。
根据分区技术,有一些技巧:
1,若索引的大小> RAM,考虑选用分区,不采用索引;
2,尽量不采用Primary Key做分区的key;
3,当CPU性能高的时候,考虑使用Archive存储引擎;
4,对于大量的历史数据,考虑使用Archive+PARTITION。
总之,
1,MySQL分区技术是一种逻辑的水平分表技术;
2,它只访问需要访问的分区,从而提高性能;
3,支持range, hash, key, list和复合分区方法;
4,支持MySQL服务器所支持的任何存储引擎;
5,除了Key分区方法,Partition的key 必须是整数(或者能转化成整数)。
参考:
[1]http://baidutech.blog.51cto.com/4114344/748675
[2]http://baidutech.blog.51cto.com/4114344/748627
MYSQL优化_MYSQL分区技术[转载]的更多相关文章
- MySQL的表分区(转载)
MySQL的表分区(转载) 一.什么是表分区 通俗地讲表分区是将一大表,根据条件分割成若干个小表.mysql5.1开始支持数据表分区了. 如:某用户表的记录超过了600万条,那么就可以根据入库日期将表 ...
- mysql优化之分区
mysql分区类型 日常开发中我们经常会遇到大表的情况,所谓的大表是指存储了百万级乃至千万级条记录的表.这样的表过于庞大,导致数据库在查询和插入的时候耗时太长,性能低下,如果涉及联合查询的情况,性能会 ...
- MySQL表分区技术
MySQL表分区技术 MySQL有4种分区类型: 1.RANGE 分区 - 连续区间的分区 - 基于属于一个给定连续区间的列值,把多行分配给分区: 2.LIST 分区 - 离散区间的分区 - 类似于按 ...
- [转载] 单表60亿记录等大数据场景的MySQL优化和运维之道 | 高可用架构
原文: http://mp.weixin.qq.com/s?__biz=MzAwMDU1MTE1OQ==&mid=209406532&idx=1&sn=2e9b0cc02bdd ...
- MySQL分区技术 (一)
4:MySQL 分区技术(是mysql 5.1以版本号后開始用->是甲骨文mysql技术团队维护人员以插件形式插入到mysql里面的技术) 眼下,针对海量数据的优化主要有2中方法: 1:大表拆成 ...
- mysql 表分区技术
表分区,是指根据一定规则,将数据库中的一张表分解成多个更小的,容易管理的部分.从逻辑上看,只有一张表,但是底层却是由多个物理分区组成. 表分区有什么好处: a.分区表的数据可以分布在不同的物理设备上, ...
- mysql的分区技术
一.概述 当 MySQL的总记录数超过了100万后,会出现性能的大幅度下降吗?答案是肯定的,但是,性 能下降>的比率不一而同,要看系统的架构.应用程序.还有>包括索引.服务器硬件等多种因素 ...
- mysql优化, 删除数据后物理空间未释放(转载)
mysql优化, 删除数据后物理空间未释放(转载) OPTIMIZE TABLE 当您的库中删除了大量的数据后,您可能会发现数据文件尺寸并没有减小.这是因为删除操作后在数据文件中留下碎片所致.OPTI ...
- 4个MySQL优化工具AWR,帮你准确定位数据库瓶颈!(转载)
对于正在运行的mysql,性能如何,参数设置的是否合理,账号设置的是否存在安全隐患,你是否了然于胸呢? 俗话说工欲善其事,必先利其器,定期对你的MYSQL数据库进行一个体检,是保证数据库安全运行的重要 ...
随机推荐
- JavaWeb验证码的使用
在Java Web开发中,我们经常需要使用到验证码功能,一般情况下,我们可以将产生的验证码保存到服务器端中的session中,这种方式中,是使用服务器来保证验证码的功能.另外,我们也可以采用js产生验 ...
- SpringBoot实践 - SpringBoot+MySql+Redis
大家都知道redis的强大之处,在目前应用上也是大显神威. 先说说他的优点: 1 读写性能优异 2 支持数据持久化,支持AOF日志和RDB快照两种持久化方式 3 支持主从复制,主机会自动将数据同步到从 ...
- JavaScript 基本类型值-Number类型
▓▓▓▓▓▓ 大致介绍 在JavaScript的内部采用IEEE754格式来表示数字,所以不区分整数和浮点数,都是用64位浮点数的形式储存.就是说,在JavaScript内部,就根本没有小数.但是有些 ...
- centos快速安装redis
mkdir redis cd redis wget http://labfile.oss.aliyuncs.com/files0422/redis-2.8.9.tar.gz 解压 tar -xvfz ...
- Redis服务器搭建
下载并解压redis,然后进入redis所在目录 编译安装 make && make install 启动redis 服务 (加上&表示在后台运 ...
- JavaScript两个变量交换值(不使用临时变量)
概要 本文主要描述,如何不使用中间值,将两个变量的值进行交换. 一.普通做法 var a = 1, b = 2, tmp; tmp = a; a = b; b = tmp; 普通的做法就是声明多一 ...
- iOS开发之仿射变换示例总结
本篇博客比较简单,但还是比较实用的.其中的示例依然使用Swift3.0来实现,该博客算是下篇博客的一个引子,因为我们下篇博客要介绍使用Swift开发iOS应用中常用的一些Extension.而在这些E ...
- 把Eclipse项目转换成Maven项目
把Maven项目转换成Eclipse项目只要使用Maven的Eclipse插件就能做到 mvn eclipse:eclipse 其实Maven的Eclipse插件也有把Eclipse项目转换成Mave ...
- Ionic2 开发笔记(1)ionic2 +angular2搭建
1.去node.js官网下载对应版本https://nodejs.org/en/(不会请看OnsenUi搭载,里面有详细过程) 2.然后通过npm下载Ionic和cordova $ npm insta ...
- node.js爬虫爬取拉勾网职位信息
简介 用node.js写了一个简单的小爬虫,用来爬取拉勾网上的招聘信息,共爬取了北京.上海.广州.深圳.杭州.西安.成都7个城市的数据,分别以前端.PHP.java.c++.python.Androi ...