mysql分区方案的研究
笔者觉得,分库分表确实好的。但是,动不动搞分库分表,太麻烦了。分库分表虽然是提高数据库性能的常规办法,但是太麻烦了。所以,尝试研究mysql的分区到底如何。
之前写过一篇文章,http://www.cnblogs.com/wangtao_20/p/7115962.html 讨论过订单表的分库分表,折腾起来工作量挺大的,需要多少技术去折腾。做过的人才知道有多麻烦
要按照什么字段切分,切分数据后,要迁移数据;分库分表后,会涉及到跨库、跨表查询,为了解决查询问题,又得用其他方案来弥补(比如为了应对查询得做用户订单关系索引表)。工作量确实不小。
从网上也可以看到,大部分实施过的人(成功的)的经验总结:水平分表,不是必须的,能不做,尽量不做。
一、探讨分区的原理
了解分区到底在做什么,存储的数据文件有什么变化,这样知道分区是怎么提高性能的。
实际上:每个分区都有自己独立的数据、索引文件的存放目录。本质上,一个分区,实际上对应的是一个磁盘文件。所以分区越多,文件数越多。
现在使用innodb存储较多,mysql默认的存储引擎从mysiam变为了innodb了。
以innodb来讨论:
innodb存储引擎一张表,对应两个文件:表名.ibd、表名.frm。
如果分区后,一个分区就单独一个ibd文件,如下图:

将fs_punch_in_log表拆分成4个分区,上图中看到,每个分区就变成一个单独的数据文件了。mysql会使用"#p#p1"来命名数据文件,1是分区的编号。总共4个分区,最大值是4。
分表的原理,实际上类似,一个表对应一个数据文件。分表后,数据分散到多个文件去了。性能就提高了。
分区后的查询语句
语句还是按照原来的使用。但为了提高性能。还是尽量避免跨越多个分区匹配数据。
如下图,由于表是按照id字段分区的。数据分散在多个分区。现在使用user_id作为条件去查询。mysql不知道到底分配在哪个分区。所以要去全部分区扫描,如果每个分区的数据量大,这样就耗时很长了。

分区思路和分区语句
id字段的值范围来分区:在1-2千万分到p0分区,4千万到-6千万p1分区。6千万到8千万p2分区。依此推算下去。这样可以分成很多的分区了。
为了保持线性扩容方便。那么只能使用range范围来算了。
sql如下
CREATE TABLE `fs_punch_in_log` (
`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键自增' ,
`user_id` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '签到的用户id' ,
`punch_in_time` int(10) UNSIGNED NULL DEFAULT NULL COMMENT '打卡签到时间戳' ,
PRIMARY KEY (`id`)
) partition BY RANGE (id) (
PARTITION p1 VALUES LESS THAN (40000000),
PARTITION p2 VALUES LESS THAN (80000000),
PARTITION p3 VALUES LESS THAN (120000000),
PARTITION p4 VALUES LESS THAN MAXVALUE
);
以上语句经过笔者测验,注意点:
- 按照hash均匀分散。传递给分区的hash()函数的值,必须是一个整数(hash计算整数计算,实现均匀分布)。上面的id字段就是表的主键,满足整数要求。
- partition BY RANGE 中的partition BY表示按什么方式分区。RANGE告诉mysql,我使用范围分区。
情况:如果表结构已经定义好了,里面有数据了,怎么进行分区呢?使用alter语句修改即可,经过笔者测验了。
ALTER TABLE `fs_punch_in_log`
PARTITION BY RANGE (id)
( PARTITION p1 VALUES LESS THAN (40000000),
PARTITION p2 VALUES LESS THAN (80000000),
PARTITION p3 VALUES LESS THAN (120000000),
PARTITION p4 VALUES LESS THAN MAXVALUE )
注:由于表里面已经存在数据了,进行重新分区,mysql会把数据按照分区规则重新移动一次,生成新的文件。如果数据量比较大,耗时间比较长。
二、四种分区类型
mysql分区包括四种分区方式:hash分区、按range分区、按key分区、list分区。
四种有点多,实际上,为了好记,把类再缩小点,就两大类方式进行分区:一种是计算hash值、一种是按照范围值。
其实分库分表的时候,也会用到两大类,hash运算分、按值范围分。
1、HASH分区
有常规hash和线性hash两种方式。
- 常规hash是基于分区个数取模(%)运算。根据余数插入到指定的分区。打算分4个分区,根据id字段来分区。
怎么算出新插入一行数据,需要放到分区1,还是分区4呢? id的值除以4,余下1,这一行数据就分到1分区。
常规hash,可以让数据非常平均的分布每一个分区。比如分为4个取,取余数,余数总是0-3之间的值(总到这几个分区去)。分配打散比较均匀。
但是也是有缺点的:由于分区的规则在创建表的时候已经固定了,数据就已经打散到各个分区。现在如果需要新增分区、减少分区,运算规则变化了,原来已经入库的数据,就需要适应新的运算规则来做迁移。
实际上在分库分表的时候,使用hash方式,也是数据量迁移的问题。不过还好。
针对这个情况,增加了线性hash的方式。
- 线性HASH(LINEAR HASH)稍微不同点。
实际上线性hash算法,就是我们memcache接触到的那种一致性hash算法。使用虚拟节点的方式,解决了上面hash方式分区时,当新增加分区后,涉及到的数据需要大量迁移的问题。也不是不需要迁移,而是需要迁移的数据量小。
在技术实现上:线性哈希功能使用的一个线性的2的幂(powers-of-two)运算法则,而常规哈希使用的是求哈希函数值的模数。
线性哈希分区和常规哈希分区在语法上的唯一区别在于,在“PARTITION BY”子句中添加“LINEAR”关键字。
两者也有有相同的地方:
- 都是均匀分布的,预先指定n个分区,然后均匀网几个分区上面分布数据。根据一个字段值取hash值,这样得到的结果是一个均匀分布的值。后面添加新的分区多少需要考虑数据迁移。
- 常规HASH和线性HASH,因为都是计算整数取余的方式,那么增加和收缩分区后,原来的数据会根据现有的分区数量重新分布。
- HASH分区不能删除分区,所以不能使用DROP PARTITION操作进行分区删除操作;
考虑以后迁移数据量少,使用线性hash。
2、按照range范围分区
范围分区,可以自由指定范围。比如指定1-2000是一个分区,2000到5000千又是一个分区。范围完全可以自己定。后面我要添加新的分区,很容易吗?
3、按key分区
类似于按HASH分区,区别在于KEY分区只支持计算一列或多列,且MySQL服务器提供其自身的哈希函数。必须有一列或多列包含整数值。
4、按list方式分区
可以把list看成是在range方式的基础上的改进版。list和range本质都是基于范围,自己控制范围。
range是列出范围,比如1-2000范围算一个分区,这样是一个连续的值。
而list分区方式是枚举方式。可以指定在1,5,8,9,20这些值都分在第一个分区。从list单词的字面意思命名暗示就是列表,指定列表中出现的值都分配在第几个分区。
三、如何根据业务选择分区类型
1、何时选择分区,何时选择分表
分表还是比分区更加灵活。在代码中可以自己控制。一般分表会与分库结合起来使用的。在进行分表的时候,顺带连分库方案也一起搞定了。
分表分库,性能和并发能力要比分区要强。分表后,有个麻烦点:自己需要修改代码去不同的表操作数据。
代码很多处要做专门的匹配如下:
非常适合业务刚刚起步的时候,能不能做起来,存活期是多久不知。不用把太多精力花费在分库分表的适应上。
mysql分区方案的研究的更多相关文章
- mysql分区研究
表分区学习 1. 概述 1.1. 优点: l 将表分区比一个表在单个磁盘或者文件系统存储能够存储更多数据 l 可以通过drop分区删除无用数据,也可以通过增加分区添加数据 l 查询可以通过分区裁剪进行 ...
- 由mysql分区想到的分表分库的方案
在分区分库分表前一定要了解分区分库分表的动机. 对实时性要求比较高的场景,使用数据库的分区分表分库. 对实时性要求不高的场景,可以考虑使用索引库(es/solr)或者大数据hadoop平台来解决(如数 ...
- mysql分区
<?php /* 分区 目录 18.1. MySQL中的分区概述 18.2. 分区类型 18.2.1. RANGE分区 18.2.2. LIST分区 18.2.3. HASH分区 18.2.4. ...
- 第18章:MYSQL分区
第18章:分区 目录 18.1. MySQL中的分区概述 18.2. 分区类型 18.2.1. RANGE分区 18.2.2. LIST分区 18.2.3. HASH分区 18.2.4. KEY分区 ...
- ubuntu系统分区方案
一.各文件及文件夹的定义 /bin:bin是binary(二进制)的缩写.存放必要的命令 存放增加的用户程序. /bin分区,存放标准系统实用程序./boot:这里存放的是启动LINUX时使用的一些核 ...
- Mysql 分区详解
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt120 一.什么是表分区通俗地讲表分区是将一大表,根据条件分割成若干个小表.m ...
- linux 分区方案
背景 之前安装过linux好多次,也学习过好几次,竟然也是一直没开窍,这次不知为啥醒悟了.了解了linux的分区道道.总结起来就是分区主要是根目录(类似c盘),swap,boot(必须有的, win ...
- mysql 分区说明
当 MySQL的总记录数超过了100万后,性能会大幅下降,可以采用分区方案 分区允许根据指定的规则,跨文件系统分配单个表的多个部分.表的不同部分在不同的位置被存储为单独的表. 1.先看下innodb的 ...
- Ubuntu分区方案归总
更新时间:2010-8-26 一.各文件及文件夹的定义 /bin:bin是binary(二进制)的缩写.存放必要的命令 存放增加的用户程序. /bin分区,存放标准系统实用程序. /boot: ...
随机推荐
- 一个不错的Node.js进阶学习引导
https://cnodejs.org/topic/58ad76db7872ea0864fedfcc
- curl get请求添加header头信息
function get($url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_HTTPGET, true); curl_setopt($ch, CU ...
- Urozero Autumn 2016. UKIEPC 2016
B. Build a Boat 首先求出每块船舱的面积$S$,然后进行$m$次二分,得到每个切割线的位置. 为了计算某个切割线形成的区域的面积,需要将多边形整理成上边界和下边界,分别二分出断点位置,中 ...
- Yii2 查询构建器 QueryBuilder
查询构造器 QueryBuilder 1.什么是查询构建器 查询构建器也是建立在 DAO 基础之上,可让你创建程序化的.DBMS 无关的 sql 语句,并且这样创建的 sql 语句比原生的 sql 语 ...
- 02-CSS&JS
今日目标 使用CSS完成网站首页的优化 使用CSS完成网站注册页面的优化 使用JS完成简单的数据校验 使用JS完成图片轮播效果 教学目标: - 了解CSS的概念 - 了解CSS的引入方式 - 了解CS ...
- 新浪SAE创建微信模板消息应用与SVN的使用
本地项目源文件必须放在应用名目录下面的数字目录里面.如:D:\SVN\xtmp1\1 我们在前面讲述在新浪SAE中如何建站,今天我们来详解如何上传文件.新浪SAE中是不允许用FTP来上传的.我们只能用 ...
- C盘清理(安装Visual Studio 或者Office后)
安装过Office,可能会存在一个C:\\MSOCache的隐藏目录,如果在D盘安装,这个文件夹可能会在D盘根目录下.该目录为Offices安装组件的目录,理解为安装包即可,如果日后不再修改OFFIC ...
- list-列表练习
#list列表取值更方便灵活 列表.数组说的都是1个东西#列表中每个字符都有一个编号,就是我们说的下标,从0开始#如果你输入的下标在列表中不存在,会报下标越界的错误 1.查询user表中下标为0的记录 ...
- 用python实现ARP欺骗
首先介绍一个python第三方库--Scapy,这个库不是标准库,默认是没有的,需要安装,不过在kali-linux里边是默认安装的, 这里我用kali做攻击者,xp做受害者 关于Scapy Scap ...
- ConditionalOnProperty
配置Spring Boot通过@ConditionalOnProperty来控制Configuration是否生效 1.matchIfMissing属性:从application.properties ...