九、分区、分库、分表
?9.1 MySQL分区 ??一般情况下我们创建的表对应一组存储文件,使用MyISAM存储引擎时是一个.MYI和.MYD文件,使用Innodb存储引擎时是一个.ibd和.frm(表结构)文件。当数据量较大时(一般千万条记录级别以上),MySQL的性能就会开始下降,这时我们就需要将数据分散到多组存储文件,保证其单个文件的执行效率。这么做有以下好处:
逻辑数据分割
提高单一的写和读应用速度
提高分区范围读查询的速度
分割数据能够有多个不同的物理文件路径
高效的保存历史数据
??查看当前数据库是否支持分区:
-- MySQL5.6以及之前版本
SHOW VARIABLES LIKE '%partition%';
-- MySQL5.6
show plugins;
?9.1.1 分区类型及操作 ??①RANGE分区:基于属于一个给定连续区间的列值,把多行分配给分区。mysql将会根据指定的拆分策略,把数据放在不同的表文件上。相当于在文件上被拆成了小块。但是,对外给客户的感觉还是一张表,透明的。按照 range 来分,就是每个库一段连续的数据,这个一般是按比如时间范围来的,比如交易表,销售表等,可以根据年月来存放数据。可能会产生热点问题,大量的流量都打在最新的数据上了。range 来分,好处在于扩容的时候很简单。
??②LIST分区:类似于按RANGE分区,每个分区必须明确定义。它们的主要区别在于,LIST分区中每个分区的定义和选择是基于某列的值从属于一个值列表集中的一个值(比如按奇偶数分),而RANGE分区是从属于一个连续区间值的集合。
??③HASH分区:基于用户定义的表达式的返回值来进行选择分区,该表达式使用将要插入到表中的这些行的列值进行计算。这个函数可以包含MySQL 中有效的、产生非负整数值的任何表达式。hash 分区,好处在于可以平均分配每个库的数据量和请求压力;坏处在于扩容起来比较麻烦,会有一个数据迁移的过程,之前的数据需要重新计算 hash 值重新分配到不同的库或表。
??④KEY分区:类似于按HASH分区,区别在于KEY分区只支持计算一列或多列,且MySQL服务器提供其自身的哈希函数。必须有一列或多列包含整数值。
??问题1:看上去分区表很好,为什么大部分互联网还是更多的选择自己分库分表来水平扩展呢?
分区表,分区键设计不太灵活,如果不走分区键,很容易出现全表锁
一旦数据并发量上来,如果在分区表实施关联,就是一个灾难
自己分库分表,自己掌控业务场景与访问模式,可控
??问题2:随着业务的发展,业务越来越复杂,应用的模块越来越多,总的数据量很大,高并发读写操作均超过单个数据库服务器的处理能力怎么办?
??这个时候就出现了数据分片,数据分片指按照某个维度将存放在单一数据库中的数据分散地存放至多个数据库或表中。数据分片的有效手段就是对关系型数据库进行分库和分表。分库分表区别于分区的是,分区一般都是放在单机里的,用的比较多的是时间范围分区,方便归档。只不过分库分表需要代码实现,分区则是mysql内部实现。分库分表和分区并不冲突,可以结合使用。
?9.2 MySQL分表 ??分表有两种分割方式,一种垂直拆分,另一种水平拆分。
?9.2.1 垂直拆分 【Mysql|Mysql精华总结07——分区、分库、分表】??垂直分表,通常是按照业务功能的使用频次,把主要的、热门的字段放在一起做为主要表。然后把不常用的,按照各自的业务属性进行聚集,拆分到不同的次要表中;主要表和次要表的关系一般都是一对一的。
?9.2.2 水平拆分(数据分片) ??单表的容量不超过500W,否则建议水平拆分。是把一个表复制成同样表结构的不同表,然后把数据按照一定的规则划分,分别存储到这些表中,从而保证单表的容量不会太大,提升性能;当然这些结构一样的表,可以放在一个或多个数据库中。水平分割的几种方法:
??使用MD5哈希,做法是对UID进行md5加密,然后取前几位(我们这里取前两位),然后就可以将不同的UID哈希到不同的用户表(user_xx)中了。
??还可根据时间放入不同的表,比如:article_201601,article_201602。
??按热度拆分,高点击率的词条生成各自的一张表,低热度的词条都放在一张大表里,待低热度的词条达到一定的条数后,再把低热度的表单独拆分成一张表。
??根据ID的值放入对应的表,第一个表user_0000,第二个100万的用户数据放在第二个表user_0001中,随用户增加,直接添加用户表就行了。
文章图片
??水平拆分会使单表数据量下降,由于单表数量下降,常见的查询操作由于减少了需要扫描的记录,使得单表单次查询所需的检索行数变少,减少了磁盘IO,时延变短
?9.3 MySQL分库 ??数据库集群环境后都是多台 slave,基本满足了读取操作; 但是写入或者说大数据、频繁的写入操作对master性能影响就比较大,这个时候,单库并不能解决大规模并发写入的问题,所以就会考虑分库。一个库里表太多了,导致了海量数据,系统性能下降,把原本存储于一个库的表拆分存储到多个库上, 通常是将表按照功能模块、关系密切程度划分出来,部署到不同库上。这减少了增量数据写入时的锁对查询的影响;但是它无法解决单表数据量太大的问题。
?9.4 分库分表后的难题 ??分布式事务的问题,数据的完整性和一致性问题。
??数据操作维度问题:用户、交易、订单各个不同的维度,用户查询维度、产品数据分析维度的不同对比分析角度。跨库联合查询的问题,可能需要两次查询。跨节点的count、order by、group by以及聚合函数问题,可能需要分别在各个节点上得到结果后在应用程序端进行合并。额外的数据管理负担,如:访问数据表的导航定位。额外的数据运算压力,如:需要在多个节点执行,然后再合并计算。程序编码开发难度提升,没有太好的框架解决,更多依赖业务看如何分,如何合,是个难题。
推荐阅读
- Mysql|Mysql精华总结08——主从复制
- Mysql|Mysql精华总结06——MySQL调优
- java|工作log
- 数据库|第一节 数据类型介绍与约束语句、数据库、表的建立(包含练习题)
- 数据库|一千个不用 Null 的理由!
- 数据库|谷粒学院之讲师管理模块
- java|程序员2009精华本(china-pub首发)--百期后的新起点
- php|php学习笔记——PHP 概述
- MySQL|LeetCode刷题(python)—— 182. 查找重复的电子邮箱