本身对mysql的一点理解吧,固然技术有限,就借鉴的一些大佬的文章,但愿能帮助到你们!( ̄▽ ̄)ノhtml
1.什么是mysql?mysql
mysql是关系型数据库,比较常见的关系型数据库有mysql/oracle/sql server/sqlite ;存数据使用的是表,这样的话结构比较固定,易于维护,咱们一般使用crud去操做表中的数据;这里的crud就是insert,delete,update,selectredis
与之相对的是非关系型数据库,如redis/mongoDB,是一种key-value形式的存储,不理解的能够简单的看做json那样存储的;算法
至于二者之间的优缺点能够简单参考这个大哥的博客sql
2.mysql中的sql语言有几种?数据库
在mysql中,有4种语言:json
(1)DDL -- Data Definition Language,中文是数据库定义语言,也就是create(建立数据库或者数据表),alter(修改数据表相关信息),drop(删除数据库或者数据表)这几个经常使用关键字,数据结构
只有建立表的时候,或者咱们后期须要给表加索引之类的可能会用到,日常用的比较少oracle
(2)DML-- Data Manipulation Language,中文是数据库操做语言,这个也就是咱们经常使用的crud操做,注意,咱们还须要记住一个explain关键字,这个explain是用于分析你写的sql语句执行效率的一个好用的工具,能够查看到有没有使用到索引等信息工具
(3)一笔带过
DCL:数据库控制语言,例如Grant —为用户授予权限 revoke–撤回受权权限
TCL:事务控制语言,例如Commit --保存已完成的内容,rollback —回滚
3.什么sql最影响mysql效率?
不考虑读写分离的状况下,最影响mysql的效率的就是查询语句,也就是你写的那一大串的select xx from xx这种,因此咱们通常就是优化查询语句;
4.如何分析sql的执行效率呢?
咱们要找到一些执行的很慢的sql,首先咱们须要开启mysql的慢查询日志,设置时间限制,当超过这个时间限制的就记录到日志文件中,而后咱们就用下面这种方式分析就ok了!那么怎么开启慢查询日志呢?看这里
使用explain查看sql的执行计划,以下所示,有兴趣的能够看看执行计划中每一个字段的意思,例如possible_keys 表示可能使用的索引,key 表示实际使用的索引等等,有兴趣的能够看看这个大哥的博客
注:还有一种更加细致的分析sql性能消耗的,使用show profile,有兴趣的能够看看这个
5.一般如何优化查询sql呢?
从上面咱们知道了如何分析一条sql中的效率,最经常使用的优化方案即是加索引;
6.索引是什么?
索引是个什么东西呢?这里涉及到数据结构中的一个B+树,索引在磁盘中是以文件的形式存在,其实能够看作一张表,也是会占用物理空间的!!!
通俗易懂一点的解释就是书籍目录:在word文档中目录确定也是占物理空间的对吧,并且咱们点击目录就能够直接跳转到对应的正文处,因此咱们能够大概的知道索引可能存的是实际数据的物理地址空间(后面也能够存实际的数据哦!取决于引擎)
那么问题来了,全部索引都是这么存的吗?
7.索引的分类
以innodb为例,索引分为两种:
(1)汇集(clustered)索引,也叫聚簇索引,一个表只能有一个。
(2)非汇集(unclustered)索引,也叫稀疏索引,或者叫作普通索引,多个。
看名字就以为想放弃了,其实汇集索引就是主键索引,其余的索引都叫作非汇集索引(好比联合索引,惟一索引啥的,这些都是非汇集索引的逻辑分类)
8.两种索引的不一样之处
首先说一下mysql中innodb存数据的方式,首先咱们要有这么一个想象的画面,数据库表的数据,都是存放在汇集索引下面的,下面画个图就了解了:
有这么一张表,id是主键(这里有个地方须要注意,对于innodb引擎,若是咱们在建表语句那里有指定主键,那么就ok,没有指定主键,mysql就会偷偷的建立一个主键索引,咱们是看不到的,表中也没有)
那么主键索引应该就是这样的,下图所示,这个时候实际的数据就是存到主键索引的叶子节点中的!
如今问题来了,那么非汇集索引是怎么存的呢?例如我把上表中name字段添加索引...
而后咱们思考,非汇集索引的结构也是b+树,和汇集索引同样,不一样的是叶子节点中村的就不是实际的数据了,而是主键的值;
咱们首先查询到叶子节点的主键的值,而后经过这个主键的值再到汇集索引中查询一次,才能拿到真正的数据!也就是说,经过非汇集索引查数据,通常要查询两次才行!第一次查询出来的是主键的值,第二次经过主键的值去汇集索引中查询实际的数据(用专业一点的词语叫作回表);
为了更清晰的理解汇集索引和非汇集索引,我在网上偷了一张比较好理解的图(惋惜不是b+树,可是原理同样),以下所示,左边是汇集索引,叶子节点存的是实际的数据;右边是非汇集索引,存的是汇集索引的值;
9.是否全部的非汇集索引查询的时候都须要查询两次呢(知识点:覆盖索引)?
在第8点中说了通常是查询两次,一般有 "通常" 这种词语就说明还有特殊状况;
例如仍是以上面的那个表为例,首先给name添加索引,那么看看这个sql:select id from user where name = "小王";
首先这个sql确定会走非汇集索引name,找到叶子节点的存的id为1,这时你以为还须要把1拿去再去查一次汇集索引么?确定不须要啊,由于咱们sql中只须要这个id就好了啊,已经查询出来了,为何还要去把那一条数据查询出来呢?
这个时候只须要查询一次就ok了,专业名词叫作覆盖索引,专业解释为:若是一个索引包含(或覆盖)全部须要查询的字段的值,称为‘覆盖索引’,即只需扫描索引而无须回表。
10.主键自增比较好仍是uuid比较好?
常常看到的主键是自增好点仍是随机字符串(例如雪花算法,uuid)好?其实数据量小的话是自增好,首先占用的空间小啊,uuid那么多位,另外还由于一点,这里用到一点平衡多叉树的知识,就是分裂(建议新手去看看多叉树的分裂,b+树不是很好理解,点击这里看看2-3-4树的分裂);
并且看到题目中有主键两个字,咱们就知道确定跟汇集索引有关呀!废话,由于咱们须要用到主键去构建汇集索引呀,那么若是不是自增的,好比咱们再insert数据的时候,主键分别为1,10,,5,20,4,3,1这种,为了保存平衡,那么b+树的节点就会分裂,从新组成新的节点,当数据量很大的时候,性能影响仍是很大的,而自增的话,直接就在b+树后面添加节点就好了,不须要分裂!可是使用自增还有一个坏处,就是id可预测性,简直为爬虫等一些东西打开了方便之门...
若是是在分库分表的状况下仍是用随机字符串吧,确保全局id的惟一性,有兴趣的还能够再深刻了解一下;
11.B+树为何比B树更适合做为索引,或者说为何innodb使用B+树做为索引?
这个问题答案我就借用一下这个老哥的;
其实就是要明白B树和B+树的区别,B树全部节点都存了数据,而B+树只有叶子节点才存了数据嘛,这就使得B+树的效率比较稳定,并且因为每一个叶子节点之间也有指针相互链接,这样使得范围查询会很方便,不须要从根节点再遍历一次;
12.除了B+树,你还能想到使用什么数据结构看成索引呢?
第一想法确定是hash表啊,用过hashmap的都知道,这东西是真的好用,时间复杂度O(1);
那么问题来了,这么好用的东西为何mysql的innodb引擎就是不用呢?留个印象,mysql中的MEMORY存储引擎索引默认用的是hash
例如,你想一想你把下面这些数据放到hashmap中,(1,10),(2,20),(3,30),(4,40),而后我须要找到key大于2小于4的数据,怎么找?若是我还要对key进行排序再输出呢,怎么办?
因此用hash做为索引,有几点须要注意:
(1)Hash索引仅仅能知足“=”,“IN”,不能支持范围查询
(2)对于排序操做Hash索引也知足不了
(3)Hash索引不能避免表扫描
(4)当有大量数据的Hash值相等的时候Hash索引的性能大打折扣(这个也就是hash中经典的桶碰撞问题)
13.mysql为何不用MyISAM引擎做为默认的引擎呢?
这个应该知道一点常识,MyISAM引擎不支持事务,不支持外键,默认是表锁,查询的效率比innodb要高等等, 还会常常和innodb作比较;
我再多说一点:首先,经过前面这么大的篇幅咱们知道了若是使用innodb引擎,那么主索引文件(或者汇集索引文件)和数据文件其实是放在一块儿的;
而后,MyISAM引擎引擎索引文件和数据文件是分开的!!!注意,是分开的,也就是说B+树叶子节点存放的是实际行数据的指针,例以下面这样(图是偷的( ̄▽ ̄)ノ),该引擎下全部的索引都是这样的,注意,存的是物理地址啊!
14.什么是最左匹配原则?
在说这个问题以前,咱们回忆一下,索引的逻辑分类有单列索引和组合索引吧,其中除了主键索引数据汇集索引,其余的索引都属于非汇集索引。最左原则就是对于组合索引来讲的!
还有一点,B+树索引的叶子节点是已经排序好了的,咱们才能根据索引值去走B+树查询。
例如咱们用最开始咱们的表,咱们对name和age建立一个组合索引:CREATE
INDEX
name_age_Index
ON
"user"("name", "age");
那么如今咱们须要将这个name和age当作一个总体,例如就这个组合索引的B+索引以下,我就简单画一下,顺便多添加了几行数据:
上图咱们能发现什么?首先是根据组合索引的第一个字段进行排序的,当第一个字段是同样的,才会继续对第二个字段进行排序;那么你直接使用select id from age = "5",你以为会走这个索引么?确定不会啊,由于叶子节点的age明显都不是排序的啊,怎么找啊?
因此只要有点数学基础,即便组合索引包含三列,CREATE
INDEX
name_age_Index
ON
"user"("name", "age","score");,咱们用到name和age会走索引,可是用到name和score只会走name索引,不会走score索引!
最后再奖励本身一下几个最左匹配原则的题目练习一下,点点这里
=========================截至目前时间2020/12/12==========================
后续还会记录一下mysql相关的知识,未完待续