本文已参与「新人创作礼」活动,一起开启掘金创作之路。
一、MySQL****
0. MySQL的存储引擎****
MySQL在5.1版本之前默认存储引擎为MyISAM,在此版本之后为InnoDB
MyIsam 只支持表锁,不支持事务
InnoDB 支持事务,且支持四种隔离级别
InnoDB 是聚集索引,MyISAM 是非聚集索引
InnoDB 必须有主键,MyISAM 可以没有主键,MyISAM不支持外键
MySQL 将默认存储引擎从 MyISAM 变成 InnoDB 的重要原因包括
①InnoDB 支持事务
②InnoDB 最小的锁粒度是行锁,MyISAM 最小的锁粒度是表锁
1. 存储引擎的数据结构****
两大存储引擎的数据结构都是B+树
(1) 为什么不用一般二叉树?****
二叉树的特殊化为一个链表(树叶一边倒),相当于全表扫描,效率低
(2) 为什么不用平衡二叉树呢?****
平衡二叉树相比于二叉查找树来说,查找效率更稳定,总体的查找速度也更快,但是
我们每查找一次数据就需要从磁盘中读取一个节点(也就是磁盘块),平衡二叉树每个节点只存储一个键值和数据,数据量小,查询效率低
(3) 那为什么不是 B 树而是 B+树呢?****
B树属于多叉树又名平衡多路查找树(查找路径不只两个)可以存储更多的节点数据,树的高度也会降低,因此读取磁盘的次数就少,查询效率更快
B+树是B树的一个升级版,特点如下
①B+树非叶子节点上是不存储数据的,仅存储键值,而 B 树节点中不仅存储键值,也会存储数据
innodb 中页的默认大小是 16KB,如果不存储数据,那么就会存储更多的键
值,相应的树的阶数(节点的子节点树)就会更大,树就会更矮更胖,如此一来我们查找
数据进行磁盘的 IO 次数有会再次减少,数据查询的效率也会更快。
②B+树索引的所有数据均存储在叶子节点,而且数据是按照顺序排列的,链表连着的。
那么 B+树使得范围查找,排序查找,分组查找以及去重查找变得异常简单
2. MySQL 事务****
事务四个特性的:ACID 原子性、一致性、隔离性、持久性
事务的四个隔离级别:
事务隔离级别 | 脏读读错的 | 不可重复读重复读过程中数据被修改 | 幻读重复读过程中数据被增删 | 说明 |
---|---|---|---|---|
读未提交(read-uncommitted) | 是 | 是 | 是 | 能够读取到没有被提交的数据 |
读已提交(read-committed) | 否 | 是 | 是 | 能够读到那些已经提交的数据 |
可重复读(repeatable-read) | 否 | 否 | 是 | 同一个事务中多次读取同样的记录的结果是一样的 |
串行化(serializable) | 否 | 否 | 否 | 运行完一个事务之后,才能运行其他事务 |
3. 实践中如何优化 MySQL****
(1) 最好是按照以下顺序优化****
①SQL语句及索引的优化
②数据库表结构的优化
③系统配置的优化
④硬件的优化
(2) 优化查询****
①用关联查询替代子查询。
②优化 GROUP BY 和 DISTINCT。
③建索引
④能用UNION ALL就不要用UNION
⑤尽量避免使用全表扫描语句
4. 大表优化****
当MySQL单表记录数过大时,数据库的CRUD性能会明显下降,一些常见的优化措施如下
l 限定数据的范围: 务必禁止不带任何限制数据范围条件的查询语句。比如:我们当用户在查询订单历史的时候,我们可以控制在一个月的范围内。;
l 读/写分离: 经典的数据库拆分方案,主库负责写,从库负责读;
l 缓存:使用MySQL的缓存,另外对重量级、更新少的数据可以考虑使用应用级别的缓存;
还有就是通过分库分表的方式进行优化。主要有垂直分区、垂直分表、水平分区、水平分表
5. 数据库分表方式****
(1) 垂直分区****
简单来说垂直拆分是指数据表列的拆分,把一张列比较多的表拆分为多张表
垂直拆分的优点:使得行数据变小,在查询时减少读取的Block数,减少I/O次数
垂直拆分的缺点:主键会出现冗余,需要管理冗余列,并会引起Join操作,让事务变得更加复杂
(2) 垂直分表****
把主键和一些列放在一个表,然后把主键和另外的列放在另一个表中
优点:
①减少不必要数据的查询:比如一个表中某些列常用,另外一些列不常用
②可以使数据行变小,一个数据页能存储更多数据,查询时减少I/O次数
缺点:
①扩展性较差:有些分表的策略基于应用层的逻辑算法,一旦逻辑算法改变,整个分表逻辑都会改变
②增加开发成本:对于应用层来说,逻辑算法增加开发成本
③管理冗余列,查询所有数据需要join操作
(3) 水平分区****
保持数据表结构不变,把一张表的数据分成N多个区块,区块可以在同一个磁盘上,也可以在不同的磁盘上
一张大表进行分区后,他还是一张表,不会变成二张表,只不过把存放数据的文件分成了许多小块
优点:突破磁盘I/O瓶颈,高磁盘的读写能力
水平拆分可以支持非常大的数据量,应用端改造也少,水平拆分最好分库
缺点:分片事务难以解决 ,跨界点Join性能较差,逻辑复杂
(4) 水平分表****
一张表分成N多个小表,mysql的分表是真正的分表,一张表分成很多表后,每一个小表都是完整的一张表
取数据的时候,我们可以通过总表来取,总表他不是一张表,没有数据,数据都放在分表里面,可以把总表理解成一个外壳,或者是联接池
优点:
①提高单表的并发能力:查寻一次所花的时间变短了,总表可以根据不同 的查询,将并发压力分到不同的小表里面
②提高磁盘I/O性能:本来一个非常大的.MYD文件现在也分摊到各个小表的.MYD中去了
(5) 水平分区和水平分表的区别****
MyIsam 引擎:
一张表对应三个文件,一个.MYD数据文件,.MYI索引文件,.frm表结构文件。
分表是把数据文件MYD和索引文件MYI以及表结构文件frm都进行拆分
分区是根据一定的规则把数据文件MYD和索引文件MYI进行了分割,还多出了一个.par文件,用来记录张表的分区信息
InnoDB引擎:
一张表对应两个文件.frm表结构文件和.ibd索引和数据文件
分表是把数据文件.frm文件和.ibd文件进行拆分
分区是根据一定的规则把数据文件.ibd文件进行拆分,新增.par文件(从MySql 5.7.6开始,不再创建.par文件,分区定义存储在内部数据字典中)
分区和分表的测重点不同,分表重点是存取数据时,如何提高mysql并发能力上;
而分区呢,如何突破磁盘的读写能力,从而达到提高mysql性能的目的
6. 数据库分库分表****
分库:原本存储于一个库的数据分块存储到多个库上
应用场景:1)库中表过多,2)单台机器容量不够,3)访问量太大。
分库分表解决的最大痛点是数据库单点瓶颈,这个瓶颈的产生是由现代二进制数据存储体系决定的(即 I/O 速度)。
三种方式
①不分表分库:将数据量比较大的几张表分散到不同的库,分散单库的压力
②垂直分表分库:将大表按照列拆分成多个表,然后再将这些表部署到不同的库上(关系密切的列组合划分)
②水平分表分库:将大表按照行拆分成多个表,然后再将这些表部署到不同的库上(可以看成是相同字段的分组,比如相同用户的数据)
(1) 分库分表存在的问题****
事务管理:在执行分库分表之后,由于数据存储到了不同的库上,数据库事务管理会出现困难。
关联查询:分库分表之后,难以避免会将原本逻辑关联性很强的数据划分到不同的表、不同的库上,这时,表的关联操作将受到限制
数据管理:额外的数据管理负担和数据运算压力,最显而易见的就是数据的定位问题和数据的增删改查的重复执行问题
(2) 分布式数据库中间件****
分库分表的技术方案总体上来讲分为两大类:应用层依赖类中间件、中间层代理类中间件
(3) 应用层依赖类中间件****
这类分库分表中间件的特点就是和应用强耦合,需要应用显示依赖相应的jar包,比如知名的TDDL、当当开源的sharding-jdbc、蘑菇街的TSharding、携程开源的Ctrip-DAL等。我们以sharding-jdbc为例,其架构图如下所示:
此类中间件的基本思路,就是重新实现JDBC的API,通过重新实现DataSource、PrepareStatement等操作数据库的接口,让应用层在基本不改变业务代码(需业务自行定义路由规则)的情况下透明地实现分库分表的能力。
中间件给上层应用提供熟悉的JDBC API,内部通过一系列的准备工作获取真正可执行的sql,然后底层再按照传统的方法(比如数据库连接池)获取物理连接来执行sql,最后把数据结果合并处理成ResultSet返回给应用层。
优点:无需额外部署,性能损耗低,无中心化
缺点:不支持异构语言,与应用强耦合,SQL支持能力较弱(受应用影响),连接消耗数高,需要改代码
(4) 中间层代理类中间件****
这类分库分表中间件的核心原理是在应用和数据库的连接之间搭起一个代理层,上层应用以标准的MySQL协议来连接代理层,然后代理层负责转发请求到底层的MySQL物理实例,这种方式对应用只有一个要求,就是只要用MySQL协议来通信即可
比较有代表性的产品有开创性质的Amoeba、阿里开源的Cobar、Mycat 、当当开源的sharding-proxy,奇虎360开源的Atlas等。我们以sharding-proxy为例,其架构图如下所示:
优点:支持异构语言,与应用完全解耦,SQL支持能力较强,连接消耗数低,不需要改代码
缺点:需连接消耗数,性能损耗略高,存在中心化
(5) 小结****
应用层依赖类中间件采用无中心化架构,适用于Java开发的高性能的轻量级OLTP应用(联机事务处理);
中间层代理类中间件提供静态入口以及异构语言的支持,适用于OLAP应用(联机分析处理)以及对分片数据库进行管理和运维的场景。
相对于分布式数据库,单机数据库的速度有明显的优势
采用什么样的数据库,取决于业务本身,如果单机数据库已经能满足你当前的业务需求并且也能满足可预期的未来一段时间的业务需求,那就没必要用分布式数据库。所以分布式数据库只是额外提供了一种选择,而不是对原有数据体系的完全颠覆。