一、mysql是什么
mysql是关系型数据库,用来存储数据的,那什么是数据呢:我们所看到的现象全部都是数据,Mysql是由c语言开发的。
从程序说:在java开发中--抽象出一类就是对现象的描述(在框架中mvc模式),其中m用来存储在数据库,称作为数据,而java对象的实例称之为数据库中的数据,所以说一张表对应对应的是java的定义。实例就是对应表中的数据,表的字段就是java中的属性。掌握本质才能够把数据库用好。
从架构上说:msql就是一套框架,既然是一套框架的话,就会有整体的架构,首先由下面的四个层面组成,而学框架的话需要先看整体,找到核心知识点,将几个核心层面进行抽象,抽象出来再由上往下去学。
二、mysql整体架构
在上面的图中,和存储层(文件系统)打交道是最小的,几乎是不可能的,一般 引擎层只是配置,我们和服务层打交道是最多的。外部的sql连接简单的说就是tcp连接。
①、首先会连接到连接层,主要进行线程池的连接,然后针对用户名和密码的校验,授权(大公司里面可能用到授权),mysql的所有的文件都存储到硬盘里面,所以会耗很高的io性能,这时肯定会有缓存支持的。
②、当第一个过程的连接成功之后,sql语句在服务层进行去执行。sql语句有两种 第一种是外部传进来的语句,第二种是是在mysql里面有存储过程,内置函数,触发器,然后用解析器来解析成mysql认识的语句。优化器:explain,执行计划,优化语句以及优化的形成,执行完上面的解析和优化器才进行真正的执行sql. 代表数据的加载。③、进入到引擎层的时候是把sql加载到内存里面去做查询和增删改查的操作。
④、进去到存储层,将数据存储到本地的磁盘上面。
⑤、最后输出数据 上面的就是整个mysql的执行流程。所有的数据都是存储在磁盘,运行的是加载到内存。
三、mysql存储引擎(内部的机制是通过索引来实现的)
我们主要的优化是在引擎层,所以主要写的是这两层。在mysql中非常重要的两个引擎是:默认使用的是Innodb
Innodb
支持行锁的,行锁的性能是高一些的,行锁的意思就是锁住某一行的数据。
执行sql语句的时候既可以锁住一张表又能锁住一行数据。
支持事务的:一致性,原子性,持久性,隔离性
还有四种特性,四种隔离级别都是innodb来执行的 数据底层的实现不一样:数据结构一样
Innodb的并发性比MyISAM的并发性要好。
不支持全文检索
数据库默认使用Innodb索引
MyISAM
表锁的,锁住的是一张表的。
不支持事务的。
数据底层的底层实现不一样:数据结构一样 支持全文索引(像like关键字....) 在相对的查询里面比较快,也不是绝对的。
什么是索引:索引不是引擎
索引只是一个数据结构
内部的机制是依靠索引-实现增删改查
为什么一个数据结构称之为索引呢?
1、当我们学习数组的时候,可以通过索引可以直接找到数据,索引是0,1,2,3,4,5像这样的数据。索引是用来检索的,检索第几行的数据的。
2、同理mysql的索引也是一样,也是用来检索数据的,在数据库里面就是一个数据结构了,在mysql里面将索引进行了一个扩展就是数据结构。3、因为和表的数据有关系,每个字段都是一个数据,把这些字段存储到一张表里面 因为这些字段在一行,用0,1,2,3,4,5这样的索引去查的话,速度是非常的慢。所以扩展下,将这些字段的关联性组成一个树形结构。
先从最简单的结构开始剖析
数据表:
平时当我们用数组的时候,hashMap,arrayList,LinkedList通过索引来查数据的速度是非常快的,可是在数据表中是不一样的,因为一个字段就是一个数据
可是在表中不是这样的:
是二维数组,可以定位到一个数据,循环查询的速度很慢,从上往下找是消耗很大的性能。而且每个字段就是一个数据,查找的时间复杂度是o(n),因为每个数据都需要遍历,有n个数据,从上往下查找的消耗的性能很大的。
当我们找一个数据的时候,都需要从上往下遍历,
二叉树:
先找到3,和3对比下直接找到2,然后最终找到4,这时只会遍历一次,这是理想的条件下。虽然能通过3找到你定位的2,虽然减少了时间,时间复杂度O(logn),折半查找方法,这就是树形结构的优化
如果在一个节点上一直排下去,太上的话,变成了单链表,也会最终导致时间的复杂度O(n),这也是特殊的情况。hash碰撞的时候才会有退化成单链表。
平衡二叉树:
时时刻刻要保持平衡,实现起来比红黑树实现起来的复杂度太难了,主要体现在算法实现上太复杂了。重新排序的话比红黑树消耗的时间要长一些。所以选择下面的红黑树
红黑树
在退化成 单链表的话,为了解决上面的问题,在hashMap中引入了红黑树,红黑树也是一种数据结构,为了解决在某个链上太长的问题,比平衡二叉树多了一个叶子节点,存的都是null,空值,通过叶子节点也能平衡这个树,不是决定的保持平衡。平衡二叉树一定要保持平衡。解决了平衡二叉树根本的原因实现起来太难的问题。
本质:防止树退化成链表,就是通过左旋和右旋来实现
缺点:虽然表面解决了O(n)的问题,如果数据库中有2百万条数据的话,这样的话树的深度变长了,用这么深的去查,性能又会降低。针对小数据量的话可以用红黑树来解决。
B-树:
由于上面的缺点就引出了B-树
将根进行横向扩展,将数据进行横排的话,就减少了深度了
依据是左边的数据永远比右边的数据要小,在每个节点上既可以存储索引值又可以存储数据
优点:两级的性能只需要遍历一次就可以了,针对数据量非常大的情况下
例如:数据库,文件系统,fastdfs。
缺点:在mysql查找的时候,它是不支持范围查找的,如果查范围的话,上下遍历的查找的话是很耗性能的,所以不支持范围查找。
B+树:mysql直接就是B+树
1、这时每个节点(不会存储任何的数据)就有一个叶子节点存在,存储数据的节点就称之为叶子节点,最底层存储相应的数据。
2、叶子节点存储的是一行的数据有前驱,和后驱的。前后都是有指针的,指向下一个节点的指针。
3、这时在范围查找的时候是非常快的,查到其中一个值就可以把下一个值查出来,使用索引来进行排序。查找范围的话,就是链表遍历了,它的查询速度就非常快了,有的时候链表在某个场景是快的,不是决定的。
1、B+树和B-树存数据量的大小和磁盘的读取原理有关,这两种结构都是解决大数据量,大文件的结构,因为大的数据量的数据的话不可能存储到内存里面去,存到磁盘。2、叶子节点的数据加上索引的大小在磁盘中默认存储的大小是4k,就是一页,这样做是为了减少IO,因为数据量是存储在磁盘上的。
3、如果一个索引指向的叶子节点的数据量超过4k的话,需要加一个节点,将叶子节点进行拆分,后面的节点也需要升级,因为叶子节点需要在同一行的,整体的树将会重排,每次的重排也是很耗性能的
4、如果数据量小于4k,就存储到当前节点的下个里面去,和并成一个4k数据量的节点,一个节点可以至少1个索引,算法是以4k为界限的。横向是可以无限延申的,但是硬盘的大小是固定的,容易出现数据溢出。
B+树和B-树的区别
1、B-树:每个节点都可以存储相应的数据,包括索引和数据,叶子节点之间没有相应从左到右的指针,只是一种横向。
2、B+树:主要用来解决B-树范围查找的问题。
3、而像红黑树,二叉树,数据解决的是小数据量的情况
硬盘:
1、在硬盘里面是有圆形磁盘的,磁盘上会有同心圆的驰道,上面会有一个时针,一个小扇形就是一个扇区,一个扇区是512字节,是它的最小的单位,一个扇区就是存储一个数据。通过时针指向每个驰道,它就会选转定位到某个扇区,扇区里面就真正的存储文件数据,读取数据,这个过程就是IO。
2、读数据的过滤:每一次读一页数据,就是一页一页的去读。一页数据是4k。大概为8个扇区,每一次读取数据的过程就称之为磁盘IO。
3、4K:与磁盘震荡的电流有关系,是通过电流来决定的。
4、为什么会一页一页的去读呢?
因为地址总线是64位,每一次读数据同时有64个线在读取数据,由于震荡频率是0101这样的二进制,而最大的扇区只能有512个字节,通过地址总线来决定的,64个总线可以一次性读取4k的数据,一次读完称之为一次IO。
有些开发商开发了磁盘的预读原理:在一次读完数据的时候,知道接下来多少页的数据能预读的话,比如说能预读10页的话,就是预读40k的数据。这就可以通过一个IO解决40k的数据。如果没有磁盘预读原理的话要有10次IO。消耗的时间是非常长的。B+树可以利用磁盘预读原理,比如一个表的数据是40k,将一个表的数据全部加载到内存,这样的话就解决了性能。这也就是mysql每一个节点是4k的原因。
InnoDB和myisam都是B+树的结构
两种引擎唯一的区别:
1、MyISAM索引实现(非聚集)
MyISAM索引文件和数据文件是分离的,数据.MYD+结构.frm+索引.MYI三个文件
2、InnoDB索引实现(聚集)
- 数据文件本身就是索引文件
- 表数据文件本身就是按B+Tree组织的一个索引结构文件
- 聚集索引-叶节点包含了完整的数据记录
- 为什么InnoDB表必须有主键,并且推荐使用整型的自增主键?
- 为什么非主键索引结构叶子节点存储的是主键值?(一致性和节省存储空间)
总结:在都是主键的情况下:InnoDB和MyISAM的效率是一样的,如果是非主键的话,在InnoDB中,需要先找到主键,然后再查数据,而在MyISAM中,也是通过非主键查表的数据。所以在非主键查询的时候,MyISAM的效率比InnoDB是快的。