MySQL(二)——MySQL的逻辑分层-存储引擎-SQL优化

目录

一、MySQL的逻辑分层

二、数据引擎

三、SQL优化

      (一)索引

                 1.索引的相关概念

                 2.B-树和B+树

                 3.索引的优缺点

                 4.索引的相分类

                 5.索引的创建

                 6.索引的删除和查看

      (二)关于SQL的性能分析


一、MySQL的逻辑分层

MySQL是我们平常用的很多的一个数据库,虽然我们每天都在用CRUD在和它打交道,但对于它内部的一些技术细节了解的并不深入。例如当我们发送一条查询语句的时候,在MySQL的服务端到底经历了什么呢?

其实MySQL逻辑上一共分为四层,分别是连接层、服务层、引擎层、存储层。到我们发送一条查询语句的时候,

1.MySQL的连接层会先为我们与MySQL建立连接并拿到SQL语句(仅仅是拿到语句,不做具体处理)

2.连接层建立连接并拿到SQL语句后就会把SQL语句交给服务层,服务层拿到SQL语句后会找服务层中对应的接口,服务层除了提供对应的增删改查接口外还有另一个重要的功能就是提供SQL优化器,服务层拿到你发送过来的SQL语句后它会做一个判断,如果它觉得你的这个SQL语句写的不够优雅,就会帮你优化然后在发送出去。

3.服务层拿到SQL并做了优化之后就会把优化后的SQL给到引擎层,引擎层会选择把SQL给到当前数据库所采用的某个存储引擎。常见的存储引擎有innoDB和MyISAM,innoDB是MySQL的默认存储引擎。关于存储引擎这一块我们在下面具体介绍,这里先大体有个概念。

4.存储引擎在的到SQL后,最后会把最终的数据交给MySQL的最后一层——存储层。我们最终的具体数据就是在存放在存储层的。

二、数据引擎

我们刚刚在上面提到在MySQL的第三层“引擎层”中有两个常见的存储引擎(当然除了这两个还有其他的不太常用),innoDB和myISAM。这两者有什么区别吗?InnoDB是MySQL的默认存储引擎,它在设计时遵循的是“事务优先”的理念,而MyISAM遵循的是“性能优先”的理念。比如说我们处理10万条数据,那么性能优先的MyISAM显然速度会更快一些,但InnoDB会更安全一些。另外InnoDB使用的是“行锁”,每次只锁一行d的数据,而MyISAM是“表锁”,一次锁一整张表的数据,所以在效率和性能上InnoDB弱一些,但在安全性上InnoDB显然更强。

    InnoDB:事务优先(适合高并发场景)、行锁

    MyISAM:性能优先,表锁

我们可以通过show engines;命令查看一下MySQL数据库支持哪些引擎,如下,除了InnoDB和myISAM,MySQL还支持很多其他的存储引擎:

既然MySQL支持这么多存储引擎,那我们能不能为某张具体的表指定某个具体的存储引擎呢?当然是可以的!现在我们就演示一下给弄张表指定具体的存储引擎

1.先来创建一个数据库并使用该数据库 create myDB;    use myDB;

2.在myDB中创建一张表,id为主键,自增步长为1(AUTO_INCREMENT=1),编码为utf-8(DEFAULT CHARSET=utf8),并指定这张表使用MyISAM存储引擎(ENGINE=MyISAM)

create table tb(

    id int(4) auto_increment,

    name varchar(5),

    dept varchar(5),

    primary key(id)

)ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

三、SQL优化

上面讲了MySQL的逻辑分层,存储引擎,其实都是为了做SQL优化做铺垫,今天就简单的对SQL优化做个简要的概述。因为一些诸如SQL性能低、执行时间长、SQL语句欠佳(主要针对多表的连接查询)、索引失效、数据库参数设置不好(如缓存区、线程数等)的原因,导致SQL效率很低,所以做SQL优化就是一件很有必要的事情,在数据量很大的时候,SQL优化就能很明显的体现出其优势。其实SQL的优化主要指的就是优化“索引(index)”,关于“索引”的具体内容我们下面分开来讲解。

(一)索引

    1.索引的相关概念:索引就相当于一本书的目录,通过目录我们一颗迅速定位书中要找的内容。MySQL中的索引也是一样,它是一种帮助MySQL高效获取数据的数据结构(树)。这里你有没有想过为什么通过“树”这种数据结构实现的索引就会提高SQL的效率呢?

这里以查询为例,结合图示简单的做一下说明,假如我们有如下的一张表,在没有引入索引之前假如我们想查询表中的一条年龄为20的数据,那么就必须几乎要遍历完整个表才能查询到这条数据;现在我们引入索引,并且以age列作为索引列来构建出一个二叉树的索引结构来,具体的构造过程是先把表中第一行的age(49)作为二叉树的头结点,然后顺序往下遍历,把小于头节点的age放到左边,大于头结点的age放到右边,表中数据遍历完以后就构造出了右图所示的二叉树索引结构。现在我们再来试着查找年龄为20的数据所需要的过程:

    1.将age为20的数据先和头结点的49比较(20<49),所以往左边走

    2.来到树形结构的第二层,继续和21比较(20<21),继续往左边走

    3.来到树形结构的第三层,和20比较(20=20),查找成功

所以你看,加上索引以后只需三次就查找成功了,可见索引确实可以提高我们SQL的查询效率。

目前大部分数据库系统及文件系统都采用B-Tree或其变种B+Tree作为索引结构,它的具体实现就在我们上面提到的引擎层的存储引擎中。像上面提到的MyISAM存储引擎就使用B-Tree来实现主键索引、唯一索引和非主键索引等。而InnoDB中的非主键索引使用的是B-Tree数据结构,主键索引则使用的是B+Tree。那么B-Tree和B+Tree到底有什么区别呢?

    2.B-Tree和B+Tree异同

       B-Tree:它类似于像上面构建的那种普通二叉树,但是B-树允许每个节点有更多的子节点(二叉树只允许有两个),B-树示意图如下:

    B-树的特点
    (1)所有键值分布在整个树中(B+Tree只分布在叶子节点中)
    (2)任何关键字出现且只出现在一个节点中
    (3)搜索有可能在非叶子节点结束
    (4)在关键字全集内做一次查找,性能逼近二分查找算法    

    B+Tree:B+树是B-树的变体,B+树的示意图为:

    从图中也可以看到,B+树与B-树的不同在于:
    (1)所有关键字存储在叶子节点,非叶子节点不存储真正的data
    (2)为所有叶子节点增加了一个链指针

    3.索引的优缺点:

       索引的弊端:1.索引本身是存储在文件中,所以一般存放在硬盘中,导致其会暂用一定的空间。

                            2.以下情况不建议用索引:a.数据量小 b.频繁更新的字段 c.很少使用的字段

                            3.索引会提高数据的“查询”效率,但是会降低“增删改”的效率

       索引的优势:1.提高查询效率:本质是降低了I/O的使用率,因为查询会到磁盘去找数据,这就涉及到I/O操作

                           2.降低了CPU的使用率:当SQL语句中有..order by的时候  因为B树索引本身就是一个排好序的结构,因此在排序时可以直接使用,而不需要再查找出结果后劳烦CPU来通过比较再进行排序。

   4.索引的分类:

      单值索引:单列 。像上面列举的age为索引列, 一个表可以有多个单值索引  

      唯一索引:同单值索引唯一不同的地方就是唯一索引不可重复,比如将入上面表中的age列有相同年龄的两个值,那么age列   就不能作为唯一索引                    

      主键索引:同唯一索引相同,都不可重复,唯一不同点就是唯一索引可以有null值,主键索引不可以有null

      复合索引:多个列构成的索引,如(name,age)两个列组合成的索引。

   5.索引的创建:

                      方式一:create 索引类型 索引名 on 表名(字段名);

                      单值索引:create index dept_index on tb(detp);

                      唯一索引:create unique index name_index on tb(name);

                      复合索引:create index dept_name_index on tb(dept,name);

                      方式二:alter table 表名 add 索引类型 索引名(字段名);

                      单值索引:alter table tb add index dept_index(dept);

                      唯一索引:alter table tb add unique index name_index(name);

                      复合索引:alter table tb add index dept_name_index(dept,name);

       注意:如果一个字段是primary key,那么该字段默认是主键索引。

   5.索引的删除和查询:   

                      删除索引:drop index 索引名 on 表名;

                                        drop index name_index on tb;

                      查询索引:show index from 表名;

(二)关于SQL的性能分析

    关于这一块的内容,我们需要清楚两个地方:

    1.分析SQL的执行计划:所谓“分析SQL的执行计划”其实指的就是通过explain+SQL语句查询我们SQL语句的执行情况,因为explian命令可以模拟服务层的SQL优化器执行SQL语句,从而让我们开发人员知道自己编写的SQL的状况。

    2.有时候MySQL服务层的SQL优化器会干扰我们的优化:有时候我们通过上面第一步的“分析SQL的执行计划”了解到自己SQL存在的问题后,然后自己做了相应的优化,但是偶尔我们会发现在SQL执行时并没有按我们优化过的SQL语句去执行。引起这个的主要原因就是我们在上边提到的服务层的SQL优化器,虽然我们做了SQL优化,但有时候SQL优化器会认为你优化的不够好,它会自动为你重新优化,而这样做有时候就会导致最后执行的结果与我们到处想要的不一样。

 

 

 

    更多的优化方法可参考官方文档:https://dev.mysql.com/doc/refman/5.5/en/optimization.html

    参考文章:https://www.jianshu.com/p/0371c9569736

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章