MySQL面试16连问

MySQL

1、什么是索引?它的原理是什么?

. . . . 如果不使用索引,数据会零散的保存在磁盘块中,查询数据需要挨个遍历每一个磁盘块,直到找到数据为止,使用索引后会将磁盘块号以树结构保存,查询数据时就不用挨个磁盘块去遍历,直接根据磁盘块号去拿到数据,会大大降低磁盘块的访问数量。

在这里插入图片描述

在关系数据库中,索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构。索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。
①索引的优点:大大加快查询速度
②索引的原理:
. . . . 索引是一个排序的表,在这个列表中存储着索引的值和包含这个值的数据所在行的物理地址或者数据的内容,在数据十分庞大的时候,索引可以大大加快查询的速度,这是因为使用索引后可以不用扫描全表来定位某行的数据,而是先通过索引表找到该行数据对应的物理地址然后访问相应的数据。
③索引的分类:
. . 从应用上来分:
. . . . 1.主键索引:主键作为索引
. . . . 2.单值索引:除主键以外的其他单个列作为索引
. . . . 3.唯一索引:索引的值必须唯一,但允许索引为null,且可以同时存在多个null索引
. . . . 4.复合索引:多个列一起作为索引
. . 从物理结构上来分:聚簇索引和非聚簇索引
④什么情况下无法利用索引?
(1)查询语句中使用LIKE关键字
在查询语句中使用 LIKE 关键字进行查询时,如果匹配字符串的第一个字符为“%”,索引不会被使用。如果“%”不是在第一个位置,索引就会被使用。【最左前缀匹配原则】
(2)查询语句中使用复合索引,但没有使用其中的第一个字段
复合索引是在表的多个字段上创建一个索引,只有查询条件中使用了这些字段中的第一个字段,索引才会被使用。
(3)查询语句中使用OR关键字
查询语句只有OR关键字时,如果OR前后的两个条件的列都是索引,那么查询中将使用索引。如果OR前后有一个条件的列不是索引,那么查询中将不使用索引。
.

.

2、MySQL存储数据的单位——页

操作系统中读取数据也是采用页作为单位,一页为4kb的数据。
注意:InnoDB也是采用的是页作为数据存取的基本单位,一页为16kb的数据。
. . . . 为什么会存在页结构呢? 假如我们不是用页作为数据的基本存取单位,那么我们每次去磁盘读取数据的时候只读取一条记录的话,当我们需要读取多条记录的时候就会造成多次磁盘的IO操作,我们都知道磁盘的IO操作相对于CPU的运行速度而言是非常慢的,因此就需要降低IO的频次,就采用页结构,让mysql一次可以存取到一页的数据,也就是一次IO操作可以获得16kb的数据。大大降低的IO的时间消耗。
. . . . 当一页存不下的时候,就会新开另外一页,并且两页之间有指针相连

在这里插入图片描述


.

.

3、聚簇索引和非聚簇索引的区别:

聚簇索引: 将数据与索引放到了一块,索引结构的叶子节点保存了行数据
非聚簇索引:将数据与索引分开存储,索引结构的叶子节点指向了数据对应的位置

. . . . 在Innodb中,使用的是聚簇索引,在聚簇索引之上创建的索引称之为辅助索引,辅助索引的叶子节点不存储数据、存储的是主键 ID。我们使用辅助索引进行查询时,首先会得到一个主键 ID,然后再使用主键 ID 去聚簇索引上找到真正的行数据,这个过程称之为回表查询。
. . . . 辅助索引的叶子节点中为什么不存地址直接指向数据?因为增删改时,不仅要对主键索引进行维护,还要对辅助索引进行维护,比较麻烦。存储主键id的话,就不需要对辅助索引进行维护,同时也减少辅助索引占用的空间大小。【如果要查询的列,在辅助索引中都有,mysql会先用辅助索引,不会直接去用主键索引,因为主键索引中存储了数据,占用空间大,辅助索引占用空间小】

补充:
①覆盖索引,指的是在一次查询中,一个索引包含了所有要查询的字段,不需要回表查询。
②回表查询,指的是在一次查询中,索引不包含所有要查询的字段,在辅助索引中得到主键ID后,需要去主键索引上根据主键ID找到真正的数据行
③索引下推, 对于联合索引(name,age,position),SELECT * FROM employees WHERE name like ‘LiLei%’ AND age = 22 AND position =‘manager’
在MySQL5.6之前的版本,在这种情况只会走name字段索引,因为根据name字段过滤完,得到的索引行里的age和position是无序的,无法很好地利用索引。只能在联合索引里匹配到名字是
‘LiLei’
开头的索引,然后拿这些索引对应的主键逐个回表,到主键索引上找出相应的记录,再比对age和position这两个字段的值是否符合。
MySQL
5.6后引入了索引下推优化,可以在索引遍历过程中,对索引中包含的所有字段先做判断,过滤掉不符合条件的记录之后再回表,可以有效的减少回表次数。使用了索引下推优化后,上面那个查询在联合索引里匹配到名字是
‘LiLei’ 开头的索引之后,同时还会在索引里过滤age和position这两个字段,拿着过滤完剩下的索引对应的主键id再回表查整行数据。

在这里插入图片描述

.

.

. . . . 在MyISAM中,使用的是非聚簇索引。非聚簇索引的两棵B+树没什么不同,节点的结构完全一致只是存储的内容不同而已,主键索引B+树的节点存储了主键,辅助键索引B+树存储了辅助键。表数据存储在独立的地方,这两颗B+树的叶子节点都使用一个地址指向真正的表数据,使用辅助索引时无需访问主键的索引树。

在这里插入图片描述

单从索引的角度来看,聚集索引和非聚集索引,谁的查找速度快?

聚集索引的查找速度更快,因为非聚集索引的数据和索引是分开存储的,通过索引找到对应数据的地址后,还要到另一个表中才能拿到真正的数据
.

.

4、MyISAM和InnoDB的区别:

①MyISAM不支持事务,但是每次查询都是原子的;InnoDb支持事务,并且支持事务的四种隔离级别。
②MyISAM支持表级锁,即每次操作是对整个表加锁;InnoDb支持行级锁及外键约束,支持并发。
③MyISAM存储表的总行数;InnoDb不存储总行数。
⑤MyISAM的主键索引采用非聚簇索引,InnoDb的主键索引采用聚簇索引。
.

.

5、为什么InnoDB表建议有主键,并且使用整型自增主键?

. . . . 当创建或设置主键的时候,mysql会自动添加一个主键索引。
因为如果我们没有自己设立自增主键,那么InnoDB就会自动帮我们选一个列的所有的数据不一样的属性作为主键(组织我们的B+树),如果表中不存在这样的列,那么InnoDB就会帮我们建一个隐藏列,用这个隐藏列来作为索引。如果我们没有自己去创建主键,那么就会给MySQL增加工作量。
. . . . 使用整型的原因:在对比的时候,整型的比较速度更快,如果使用的是字符串,还要转换为ASCLL码,并且整型的占用空间比较小
. . . . 使用自增的主键原因:在生成索引树、插入索引时,效率更高。
当使用主键为聚簇索引时,主键最好不要使用uuid,因为uuid的值太过离散,不适合排序且可能出线新增加记录的uuid,会插入在索引树中间的位置,导致索引树调整复杂度变大,消耗更多的时间和资源。

6、mysql索引的数据结构的优劣

在MySQL中使用较多的索引有Hash索引,B+树索引

①Hash索引:

. . . .哈希索引就是采用一定的哈希算法,把键值换算成新的哈希值,检索时不需要类似B+树那样从根节点到叶子节点逐级查找,只需一次哈希算法即可立刻定位到相应的位置,速度非常快。
. . . .但如果是范围查询检索,这时候哈希索引就毫无用武之地了,因为原先是有序的键值,经过哈希算法后,有可能变成不连续的了,就没办法再利用索引完成范围查询检索

在这里插入图片描述

②B+树索引:

. . . .B+树是一个平衡的多叉树,从根节点到每个叶子节点的高度差值不超过1,而且叶子节点间有指针相互链接。在B+树上的常规检索,从根节点到叶子节点的搜索效率基本相当,不会出现大幅波动,而且基于索引的顺序扫描时,也可以利用双向指针快速左右移动,效率非常高。
在绝大多数需求为单条记录查询的时候,可以选择哈希索引,查询性能最快,其余情况都用B+树索引,会更快。

在这里插入图片描述


.

.

7、MySQL的底层索引为什么要选B+树而不是B树

. . . .因为B树不管叶子节点还是非叶子节点,都会保存数据,这样导致在非叶子节点中能保存的指针数量变少(有些资料也称为扇出),指针少的情况下要保存大量数据,只能增加树的高度,导致IO操作变多,查询性能变低;
【为什么不选红黑树?由于要平衡红黑树的高度,所以每次插入和删除节点有很大的可能要大幅调整树结构】
.

.

8、B树和B+树的区别

(1)B树不管叶子节点还是非叶子节点,都会保存数据,而B+树只会在叶子节点存储数据
(2)B树叶子结点之间没有指针【范围查询速度慢】,B+树的叶子节点之间有双向的指针
【学术上的B+树是单向的,但MySQL中的B+树使用的是双向指针】
.

.

9、索引设计的原则:

. . . .①更新频繁字段不适合创建索引,因为索引中的字段被更新的时候,不仅仅要更新表中的数据,还要更新索引数据。
. . . .②基数较小的字段不要建立索引,索引效果较差,没有必要在此列建立索引
【解释:索引基数是指这个字段在表里总共有多少个不同的值,比如一张表总共100万行记录,其中有个性别字段,其值不是男就是女,那么该字段的基数就是2。如果对这种小基数字段建立索引的话,还不如全表扫描了,因为你的索引树里就包含男和女两种值,根本没法行快速的二分查找,那用索引就没有太大的意义了。 一般建立索引,尽量使用那些基数比较大的字段,就是值比较多的字段,那么才能发挥出B+树快速二分查找的优势来。】
. . . .③使用短索引,如果对长字符串列进行索引,应该指定一个前缀长度,这样能够节省大量索引空间,如果搜索词超过索引前缀长度,则使用索引排除不匹配的行,然后检查其余行是否可能匹配。
. . . .④尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可。
. . . .⑤不要创建过多的索引。索引需要额外的磁盘空间,并降低写操作的性能。在修改表内容的时候,索引会进行更新甚至重构,索引列越多,这个时间就会越长。所以只保持需要的索引有利于查询即可。
.

.

10、什么是最左前缀原则?

. . . .最左优先,以最左边的为起点任何连续的索引都能匹配上
【mysql有一个自己的算法,如果使用了索引,数据量大仍然很大,是有可能不会走索引的】
.

.

11、MySQL中锁的类型有哪些?

①基于锁的属性分类:共享锁、排他锁。
②基于锁的粒度分类:行级锁(INNODB)、表级锁(INNODB、MYISAM)、页级锁、记录锁、间隙锁、临键锁。
【行锁和表锁问的比较多】
③从对数据库的操作类型分类:乐观锁、悲观锁

  1. 共享锁
    共享锁又称读锁,简称S锁;当一个事务为数据加上读锁之后,其他事务只能对该数据加读锁,而不能对 数据加写锁,直到所有的读锁释放之后其他事务才能对其进行加持写锁。
    共享锁的特性主要是为了支持并发的读取数据,读取数据的时候不支持修改,避免出现重复读的问题。

  2. 排它锁
    排他锁又称写锁,简称X锁;当一个事务为数据加上写锁时,其他请求将不能再为数据加任何锁,直到该锁释放之后,其他事务才能对数据进行加锁。
    排他锁的目的是在数据修改时候,不允许其他人同时修改,也不允许其他人读取。避免了出现脏数据和脏读的问题。

  3. 行锁【包括记录锁、间隙锁、临建锁】
    行锁是指上锁的时候锁住的是表的某一行或多行记录,其他事务访问同一张表时,只有被锁住的记录不能访问,其他的记录可正常访问;
    特点:粒度小,加锁比表锁麻烦,不容易冲突,相比表锁支持的并发要高;

  4. 表锁
    表锁是指上锁的时候锁住的是整个表,当下一个事务访问该表的时候,必须等前一个事务释放了锁才能 进行对表进行访问;
    特点: 粒度大,加锁简单,容易冲突;

  5. 记录锁
    记录锁也属于行锁中的一种,只不过记录锁的范围只是表中的某一条记录,记录锁是说事务在加锁后锁住的只是表的某一条记录。
    精准条件命中,并且命中的条件字段是唯一索引
    加了记录锁之后数据可以避免数据在查询的时候被修改的重复读问题,也避免了在修改的事务未提交前 被其他事务读取的脏读问题。

  6. 页锁
    页级锁是MySQL中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快,但冲突多,行级冲突少,但速度慢。所以取了折衷的页级,一次锁定相邻的一组记录。
    特点:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般

  7. 间隙锁
    属于行锁中的一种,间隙锁是在事务加锁后其锁住的是表记录的某一个区间,当表的相邻ID之间出现空隙则会形成一个区间,遵循左开右闭原则。
    范围查询并且查询未命中记录,查询条件必须命中索引、间隙锁只会出现在REPEATABLE_READ(重复读)的事务级别中。

  8. 临建锁
    也属于行锁的一种,并且它是INNODB的行锁默认算法,总结来说它就是记录锁和间隙锁的组合,临键锁会把查询出来的记录锁住,同时也会把该范围查询内的所有间隙空间也会锁住,再之它会把相邻的下一个区间也会锁住
    触发条件:范围查询并命中,查询命中了索引。
    结合记录锁和间隙锁的特性,临键锁避免了在范围查询时出现脏读、重复读、幻读问题。加了临键锁之后,在范围区间内数据不允许被修改和插入。
    .

.

12、事务的基本特性和隔离级别

事务基本特性ACID分别是:
. . . .①A原子性指的是一个事务中的操作要么全部成功,要么全部失败。
. . . .②C一致性指的是数据库总是从一个一致性的状态转换到另外一个一致性的状态。
. . . .③I隔离性指的是一个事务的修改在最终提交前,对其他事务是不可见的。
. . . .④D持久性指的是一旦事务提交,所做的修改就会永久保存到数据库中

四个隔离级别:
①read uncommitted 读未提交:
. . . .在该隔离级别中,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。
. . . .可能会出现:脏读、不可重复读。
②read committed 读已提交:
. . . .一个事务只能看见已经提交事务的结果。
. . . .可能会出现:不可重复读、幻读。
③repeatable read 可重复读:
. . . .这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。
. . . .可能会出现:幻读。
④serializable 串行
. . . .这是最高的隔离级别,它通过强制事务排序,在每个读的数据行上加上共享锁,使之不可能相互冲突,从而解决幻读问题
.

.

13、怎么保证事务的ACID

. . . .原子性由undo log(回滚日志)保证,它记录了需要回滚的日志信息,事务回滚时撤销已经执行成功的sql
. . . .一致性由其他三大特性保证、程序代码要保证业务上的一致性
. . . .隔离性由MVCC来保证
. . . .持久性由内存和redo log(重做日志)来保证,mysql修改数据的同时,在内存和redo log记录这次操作,宕机的时候可以从redo log恢复

.

.

14、什么是MVCC?

. . . .MVCC就是多版本并发控制:读取数据时通过一种类似快照的方式将数据保存下来,这样读锁就和写锁不冲突了,不同的事务session会看到自己特定版本的数据。
. . . .版本链MVCC只在 READ COMMITTED 和 REPEATABLE READ 两个隔离级别下工作。其他两个隔离级和MVCC不兼容, 因为 READ UNCOMMITTED 总是读取最新的数据行, 而不是符合当前事务版本的数据行。而 SERIALIZABLE 则会对所有读取的行都加锁。
MVVC原理:
. . . .MVVC的实现主要依靠undo日志版本链,在mysql中有一个undo日志版本链,在事务第一次查询的时候,会生成的一个read view视图,后面所有查询的数据都会根据undo日志版本链,去read view里,按照一定的规则去比对,拿到对应的数据
.

.

15、并发事务带来的问题:

. . . .①脏读:事务A读取到了事务B已经修改但尚未提交的数据
. . . .②不可重复读:事务A内部的相同查询语句在不同时刻读出的结果不一致,不符合隔离性【可能因为其他事务对数据进行了修改,所以读出结果不一致】
. . . .③幻读:一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据
.

.

16、数据库的三大范式

. . . .第一范式(1NF):数据库的表每一列都是不可分割的原子数据,即每一列不可再拆分
. . . .第二范式(2NF):满足 1NF 前提下,非主属性全部依赖主键【消除部分函数依赖】
. . . .第三范式(3NF):满足 2NF 前提下,非主属性之间互不依赖【消除传递依赖】

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习编程?其实不难,不过在学习编程之前你得先了解你的目的是什么?这个很重要,因为目的决定你的发展方向、决定你的发展速度。
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面设计类、前端与移动、开发与测试、营销推广类、数据运营类、运营维护类、游戏相关类等,根据不同的分类下面有细分了不同的岗位。
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生学习Java开发,但要结合自身的情况,先了解自己适不适合去学习Java,不要盲目的选择不适合自己的Java培训班进行学习。只要肯下功夫钻研,多看、多想、多练
Can’t connect to local MySQL server through socket \'/var/lib/mysql/mysql.sock问题 1.进入mysql路径
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 sqlplus / as sysdba 2.普通用户登录
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服务器有时候会断掉,所以写个shell脚本每五分钟去判断是否连接,于是就有下面的shell脚本。
BETWEEN 操作符选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。
假如你已经使用过苹果开发者中心上架app,你肯定知道在苹果开发者中心的web界面,无法直接提交ipa文件,而是需要使用第三方工具,将ipa文件上传到构建版本,开...
下面的 SQL 语句指定了两个别名,一个是 name 列的别名,一个是 country 列的别名。**提示:**如果列名称包含空格,要求使用双引号或方括号:
在使用H5混合开发的app打包后,需要将ipa文件上传到appstore进行发布,就需要去苹果开发者中心进行发布。​
+----+--------------+---------------------------+-------+---------+
数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声明一个数组变量,比如 numbers,然后使用 nu...
第一步:到appuploader官网下载辅助工具和iCloud驱动,使用前面创建的AppID登录。
如需删除表中的列,请使用下面的语法(请注意,某些数据库系统不允许这种在数据库表中删除列的方式):
前不久在制作win11pe,制作了一版,1.26GB,太大了,不满意,想再裁剪下,发现这次dism mount正常,commit或discard巨慢,以前都很快...
赛门铁克各个版本概览:https://knowledge.broadcom.com/external/article?legacyId=tech163829
实测Python 3.6.6用pip 21.3.1,再高就报错了,Python 3.10.7用pip 22.3.1是可以的
Broadcom Corporation (博通公司,股票代号AVGO)是全球领先的有线和无线通信半导体公司。其产品实现向家庭、 办公室和移动环境以及在这些环境...
发现个问题,server2016上安装了c4d这些版本,低版本的正常显示窗格,但红色圈出的高版本c4d打开后不显示窗格,
TAT:https://cloud.tencent.com/document/product/1340