【MySQL常见面试题】

news2024/11/24 22:34:58

索引的基本原理

索引⽤来快速地寻找那些具有特定值的记录。如果没有索引,⼀般来说执⾏查询时遍历整张表。

索引的原理:就是把⽆序的数据变成有序的查询

  1. 把创建了索引的列的内容进⾏排序

  2. 对排序结果⽣成倒排表

  3. 在倒排表内容上拼上数据地址链

  4. 在查询的时候,先拿到倒排表内容,再取出数据地址链,从⽽拿到具体数据

索引设计的原则

查询更快、占⽤空间更⼩

  1. 适合索引的列是出现在where⼦句中的列,或者连接⼦句中指定的列。

  2. 基数较⼩的表,索引效果较差,没有必要在此列建⽴索引。

  3. 使⽤短索引,如果对⻓字符串列进⾏索引,应该指定⼀个前缀⻓度,这样能够节省⼤量索引空间,如果搜索词超过索引前缀⻓度,则使⽤索引排除不匹配的⾏,然后检查其余⾏是否可能匹配。

  4. 不要过度索引。索引需要额外的磁盘空间,并降低写操作的性能。在修改表内容的时候,索引会进⾏更新甚⾄重构,索引列越多,这个时间就会越⻓。所以只保持需要的索引有利于查询即可。

  5. 定义有外键的数据列⼀定要建⽴索引。

  6. 更新频繁字段不适合创建索引。

  7. 若是不能有效区分数据的列不适合做索引列(如性别,男⼥未知,最多也就三种,区分度实在太低)。

  8. 尽量的扩展索引,不要新建索引。⽐如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可。

  9. 对于那些查询中很少涉及的列,重复值⽐较多的列不要建⽴索引。

  10. 对于定义为text、image和bit的数据类型的列不要建⽴索引。

索引覆盖和索引下推

索引覆盖(Index Covering)和索引下推(Index Pushdown)是MySQL中的两个优化技术,用于提高查询性能。

  1. 索引覆盖(Index Covering):
    索引覆盖是指查询所需的数据可以完全通过索引来获取,而无需访问实际的数据行。当一个查询只需要从索引中获取所需的列数据时,MySQL可以直接从索引中读取数据,而不需要额外的IO操作去读取实际的数据行(回表)。这样可以减少磁盘IO和内存开销,提高查询性能。

  2. 索引下推(Index Pushdown):
    索引下推是指在查询过程中,MySQL将过滤条件下推到存储引擎层级执行。通常情况下,MySQL会先根据索引定位到满足条件的数据行,然后再应用查询条件进行过滤。而索引下推可以将部分查询条件下推到存储引擎层级执行,减少了从存储引擎返回的数据量,提高了查询效率。

索引下推可以减少从存储引擎返回的数据量,减少了网络传输和内存开销。同时,索引下推还可以减少存储引擎层级的数据访问次数,提高查询性能。

需要注意的是,索引覆盖和索引下推都依赖于合适的索引设计和查询语句的优化。正确地选择和使用索引,以及编写高效的查询语句是提高查询性能的关键。

mysql索引失效场景

  1. 未满足最左匹配原则的,index(a,b,c),但是查询条件是where b= ? and c= ? 这样会导致索引失效
  2. 函数、计算、类型转换会导致索引失效
  3. 左模糊会导致索引失效
  4. or前后不管存不存在非索引的列,索引都会失效
  5. 范围查询时右边的列会索引失效,比如索引树值为 1, 2,3,4,5,6,7,8,9 ,where > 1 妥妥的索引失效了
  6. !=<> 都会导致索引失效
  7. is null 可以走索引,is not null不能走索引
  8. 查询时数据类型不一致,可能会导致索引失效,比如 varchar类型用 数字类型比对时

MySQL慢查询该如何优化

  1. 检查是否走了索引,如果没有则优化SQL利用索引(同时注意索引失效)。
  2. 如果走了索引,检查所利用的索引是否是最优索引。
  3. 检查所查询字段是否都是必须的,是否查询了过多字段,查出了多余数据。
  4. 检查表中数据是否过多,是否应该进行分库分表了。
  5. 检查数据库实例所在机器的性能配置,是否太低,是否可以适当增加资源。

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

事务基本特性ACID分别是:

**原⼦性(undo_log)**指的是⼀个事务中的操作要么全部成功,要么全部失败。

⼀致性指的是数据库总是从⼀个⼀致性的状态转换到另外⼀个⼀致性的状态。⽐如A转账给B100块钱,假设A只有90块,⽀付之前我们数据库⾥的数据都是符合约束的,但是如果事务执⾏成功了,我们的数据库数据就破坏约束了,因此事务不能成功,这⾥我们说事务提供了⼀致性的保证。

**隔离性(锁、MVCC)**指的是⼀个事务的修改在最终提交前,对其他事务是不可⻅的。

**持久性(redo_log)**指的是⼀旦事务提交,所做的修改就会永久保存到数据库中。

隔离性有4个隔离级别,分别是:

​ ● read uncommit 读未提交,可能会读到其他事务未提交的数据,也叫做脏读。

⽤户本来应该读取到id=1的⽤户age应该是10,结果读取到了其他事务还没有提交的事务,结果读取结果age=20,这就是脏读。

​ ● read commit 读已提交,两次读取结果不⼀致,叫做不可重复读。

不可重复读解决了脏读的问题,他只会读取已经提交的事务。⽤户开启事务读取id=1⽤户,查询到age=10,再次读取发现结果=20,在同⼀个事务⾥同⼀个查询

读取到不同的结果叫做不可重复读。

​ ● repeatable read 可重复复读,这是mysql的默认级别,就是每次读取结果都⼀样,但是有可能产⽣幻读。

​ ● serializable 串⾏,⼀般是不会使⽤的,他会给每⼀⾏读取的数据加锁,会导致⼤量超时和锁竞争的问题。

MVCC(Multi-Version Concurrency Control)

一、什么是MVCC

MVCC(Multi-Version Concurrency Control),多版本并发控制,是为了在读取数据时不加锁来提高读取效率和并发性的一种手段。

数据库并发有以下几种场景:

  • 读-读:不存在任何问题。

  • 读-写:有线程安全问题,可能出现脏读、幻读、不可重复读。

  • 写-写:有线程安全问题,可能存在更新丢失等。

MVCC解决的就是读写时的线程安全问题,线程不用去争抢读写锁。

当前读和快照读

MVCC所提到的读是快照读,也就是普通的select语句。快照读在读写时不用加锁,不过可能会读到历史数据。

还有一种读取数据的方式是当前读,是一种悲观锁的操作。它会对当前读取的数据进行加锁,所以读到的数据都是最新的。主要包括以下几种操作:

  • select lock in share mode(共享锁)
  • select for update(排他锁)
  • update(排他锁)
  • insert(排他锁)
  • delete(排他锁)

二、MVCC实现

  1. 回顾事务的特性
    • 原子性:通过undo_log实现。
    • 持久性:通过redo_log实现。
    • 隔离性:通过加锁(当前读)和 MVCC(快照读)实现。
    • 一致性:通过undo_log、redo_log、隔离性共同实现。
  2. 回顾事务的隔离级别
    • 读未提交:允许读取尚未提交的数据变更。可能会导致脏读、幻读或不可重复读。
    • 读已提交:允许读取已经提交的数据。可能会导致幻读和不可重复读。
    • 可重复读:对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改。可能会导致幻读。
    • 可串行化:最高隔离级别。

    在读已提交(RC)和可重复读(RR)隔离级别下的快照读,都是基于MVCC实现的!

    RC隔离级别下的事务,在每次执行查询sql语句时都会生成一个ReadView视图(注意:不是在开启事务的时候,而是执行select的时候生成),RR隔离级别在第一次读的时候会生成一个ReadView视图,之后读都会利用这个视图。

  3. MVCC实现原理

MVCC的实现,基于undo_log版本链ReadView视图实现。

undo_log版本链

在mysql存储的数据中,除了我们显式定义的字段,mysql会隐含的帮我们定义几个字段。

  • trx_id:事务id,每进行一次事务操作,就会自增1。
  • roll_pointer:回滚指针,用于找到上一个版本的数据,结合undo_log进行回滚。

在这里插入图片描述

ReadView视图

当我们用select读取数据时,这一时刻的数据会有很多个版本(例如上图有四个版本),但我们并不知道读取哪个版本,这时就靠readview来对我们进行读取版本的限制,通过readview我们才知道自己能够读取哪个版本

在一个readview快照中主要包括以下这些字段:

字段解释
m_ids当前活越的事务集合,统计所有没有提交的事务
min_trx_id这个集合中的最小事务,链尾事务id
max_trx_id这个集合中的最大事务+1,下一个将被分配的事务
creator_trx_id创建这个ReadView的事务

查找唯一可用版本

以上图为例子:

当前活越事务集合为:m_ids:[2,3,4]

链尾事务id:min_trx_id:2

链头事务id:max_trx_id:5

创建事务id:creator_trx_id:5(此处假设是通过其他select查询语句创建的ReadView,如果是通过trx=4这个事务先执行修改而后查询,则creator_trx_id = 4)

查找规则:

① 判断该版本是否为当前事务创建,如果链头事务id(4) = 当前事务id(5),可访问。

② 如果trx_id < min_trx_id,表示事务在生成ReadView之前就已经提交,可以直接访问。

③ 如果trx_id > max_trx_id,表示该事务在ReadView之后开启,不可访问,遍历下一个版本。

④ 如果min_trx_id <= trx_id <= max_trx_id,如果trx_id在m_ids里面,则不可访问;trx_id不在m_ids里面,可以直接访问。

mvcc如何实现RC和RR的隔离级别

(1)RC的隔离级别下,每个快照读都会生成并获取最新的ReadView

(2)RR的隔离级别下,只有在同一个事务第一个快照读才会创建ReadView,之后的每次快照读都使用的同一个ReadView,所以每次的查询结果都是一样的

MyISAM和InnoDB的区别

MyISAMInnoDB
事务不支持事务,但是每次查询都是原子的支持ACID的事务,支持事务的四种隔离级别
支持表级锁,即每次操作是对整个表加锁支持行级锁及外键约束:因此可以支持写并发
表总行数储存表的总行数不储存总行数
存储一个MyISAM表有三个文件:索引文件、表结构文件、数据文件一个InnoDB引擎存储在一个文件空间(共享表空间,表大小不受操作系统控制,一个表可能分布在多个文件里),也有可能为多个(设置为独立表空间,表大小受操作系统文件大小限制,一般为2G),受操作系统文件大小的限制
索引采用非聚簇索引,索引文件的数据域指向数据文件的指针。辅索引与主索引基本一致,但是辅索引不用保证唯一性主键索引采用聚簇索引(索引的数据域存储数据文件本身),辅索引的数据域存储主键的值;因此从辅索引查找数据,需要先通过辅索引找到主键值,再访问辅索引;最好采用自增主键,防止插入数据时,为维持B+数结构,文件的大调整

Explain

列名描述
id查询语句种每出现一个SELECT关键字,MySQL就会为它分配一个唯一的id值,某些子查询会被优化为join查询,那么出现的id会一样
select_typeSELECT关键字对应的那个查询的类型
table表名
partitions匹配的分区信息
type针对单表的查询方式(全表扫描、索引)(type = const , 通过主键id 或者唯一索引进行查询,type = ref | eq_ref,通过普通索引查询)
possible_keys可能用到的索引
key实际上使用的索引
key_len实际使用到的索引长度
ref当使用索引列等值查询时,与索引列进行等值匹配的对象信息
rows预估的需要读取的记录条数
filtered某个表经过搜索条件过滤后剩余记录条数的百分比
Extra一些额外的信息,比如排序等

Innodb是如何实现事务的

Innodb通过Buffer Pool,LogBuffer,Redo Log(保证持久性),Undo Log(保证原子性)来实现事务,以⼀个update语句为例:

  1. Innodb在收到⼀个update语句后,会先根据条件找到数据所在的⻚,并将该⻚缓存在Buffer Pool中。

  2. 执⾏update语句,修改Buffer Pool中的数据,也就是内存中的数据。

  3. 针对update语句⽣成⼀个RedoLog对象,并存⼊LogBuffer中。

  4. 针对update语句⽣成undolog⽇志,⽤于事务回滚。

  5. 如果事务提交,那么则把RedoLog对象进⾏持久化,后续还有其他机制将Buffer Pool中所修改的数据⻚持久化到磁盘中。

  6. 如果事务回滚,则利⽤undolog⽇志进⾏回滚。

B树和B+树的区别,为什么Mysql使⽤B+树

B树的特点:

  1. 节点排序

  2. ⼀个节点了可以存多个元素,多个元素也排序了

B+树的特点:

  1. 拥有B树的特点

  2. 叶⼦节点之间有指针

  3. ⾮叶⼦节点上的元素在叶⼦节点上都冗余了,也就是叶⼦节点中存储了所有的元素,并且排好顺序

Mysql索引使⽤的是B+树,因为索引是⽤来加快查询的,⽽B+树通过对数据进⾏排序所以是可以提⾼查询速度的,然后通过⼀个节点中可以存储多个元素,从⽽可以使得B+树的⾼度不会太⾼,在Mysql中⼀个Innodb⻚就是⼀个B+树节点,⼀个Innodb⻚默认16kb,所以⼀般情况下⼀颗两层的B+树可以存**( 16 * 1024 ÷ (8 + 6)) * ( 16K ÷ 1K ) = 18720**条左右的数据(此处假设一条数据1K,主键是bigint类型,总记录数 = 根节点指针数 * 每页记录数),然后通过利⽤B+树叶⼦节点存储了所有数据并且进⾏了排序,并且叶⼦节点之间有指针,可以很好的⽀持全表扫描,范围查找等SQL语句。

B+树能存多少数据

B+树是一种在非叶子节点存放排序好的索引而在叶子节点存放数据的数据结构,值得注意的是,在叶子节点中,存储的并非只是一行表数据,而是以页为单位存储,一个页可以包含多行表记录。非叶子节点存放的是索引键值和页指针。

那么,在MySql数据库里,一个页的大小可以通过查询语句进行查看:show variables like 'innodb_page_size;

在这里插入图片描述

可以看出MySQL数据库默认页大小为16KB,假设一条记录最大有1KB(实际上宽表一行记录才会有这么大),那么一页可以存储的数据量为16KB / 1KB = 16 条记录

根节点可以存储的指针数为16 * 1024 / ( 8 + 6 )= 1170 个指针(bigint占8个字节,指针占6个字节),从而得出两层的B+树可以存储的数据量为1170 * 16 = 18720 条记录

在这里插入图片描述

三层的B+树可以存储多少条记录呢?答案显而易见了

根节点可以储存16 * 1024 / (8 + 6)= 1170个指针,第二层每层可以存储16 * 1024 / (8 + 6)= 1170个指针,第三层每一页可以存16条数据,

那么就可以得出三层的B+树可以存储 1170 * 1170 * 16 = 21902400 条记录了。

在这里插入图片描述

MySQL有哪些锁,举例

按锁的粒度分类:

  1. 行锁:锁某行数据,锁粒度最小,并发度高
  2. 表锁:锁整张表,锁粒度最大,并发最低
  3. 间隙锁:锁的是一个区间

还可以分为:

  1. 共享锁(select … lock in share mode):也就是读锁,一个事务给某行数据加了读锁,其他事务也可以读,但是不能写。
  2. 排他锁(select … for update):也就是写锁,一个事务给某行数据加了写锁,其他事务不能读,也不能写

还可以分为:

  1. 乐观锁:并不会真正的去锁某行记录,而是通过一个版本号来实现的。(如:update … where id = #{id} and version = #{version} )
  2. 悲观锁:上面的行锁、表锁等都是悲观锁。

在事务的隔离级别实现中,就需要利用锁来解决幻读(RR级别(可重复读)会出现的问题,只会在第一个sql语句执行时生成ReadView,即使其他事务修改数据后,也不会生成新的ReadView导致读取的数据一直是一样的)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/860433.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机网络:网络通信相关概念入门

目录 一、网络发展背景二、理解网络通信三、理解IP地址1.简述IP地址2.IP地址的版本3.提高地址利用率的技术 四、理解端口1.简述端口2.使用端口的原因 五、理解网络通信协议 一、网络发展背景 网络发展背景&#xff1a; 最初的计算机是单机&#xff0c;那么单机是这样传输数据的…

谁是5G应用的狮子座?

8月5日&#xff0c;广和通公布2023年上半年财报&#xff0c;2023上半年总营业收入38.65亿元&#xff0c;同比增长59.87%。在全球经济存在诸多不确定性的背景下&#xff0c;广和通精准预判市场风向&#xff0c;制定稳健发展策略&#xff0c;业绩仍保持逆势增长。其中&#xff0c…

详谈基于布局分析的表格识别方法

基于布局分析的OCR&#xff08;Optical Character Recognition&#xff09;是一种基于页面布局信息的文本识别方法。传统的OCR系统通常依赖于表格线或者特定的格式来进行文本区域检测和字符识别&#xff0c;但对于一些表格线不全或线不清晰&#xff0c;甚至没表格线&#xff0c…

协程(一)单机--》并发--》协程

目录 一 协程的概述1.1 并行与并发1.2 线程1.3 新的思路1.4 Goroutine 二 第一个入门程序 一 协程的概述 我查看了网上的一些协程的资料&#xff0c;发现每个人对协程的概念都不一样&#xff0c;但是我认可的一种说法是&#xff1a;协程就是一种轻量级的线程框架&#xff08;K…

去趋势化一个心电图信号、信号功率谱、低通IIR滤波器并平滑信号、对滤波器引起的延迟进行补偿研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

【C语言进阶篇】关于指针的八个经典笔试题(图文详解)

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏:《C语言初阶篇》 《C语言进阶篇》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 &#x1f4cb; 前言&#x1f4ac; 指针笔试题&#x1f4ad; 笔试题 1&#xff1a;✅ 代码解析⁉️ 检验结果&…

二叉树(4)------收尾

1)最大二叉树 654. 最大二叉树 - 力扣&#xff08;LeetCode&#xff09; 题目解析: 1)首先我们找到了整个数组中最大的元素作为我们的根节点&#xff0c;然后再从左区间中找到最大的元素作为当前根节点的左子树&#xff0c;然后再从右区间里面找到最大的元素作为根节点的右子树…

【OpenVINOSharp】 基于C#和OpenVINO2023.0部署Yolov8全系列模型

基于C#和OpenVINO2023.0部署Yolov8全系列模型 1 项目简介1.1 OpenVINOTM 2 OpenVinoSharp2.1 OpenVINOTM 2023.0安装配置2.2 C 动态链接库2.3 C#构建Core推理类2.4 NuGet安装OpenVinoSharp 3 获取和转换Yolov8模型3.1 安装ultralytics3.2 导出yolov8模型3.3 安装OpenVINOTM Pyt…

杭电多校 Rikka with Square Numbers 费马平方和定理

&#x1f468;‍&#x1f3eb; Rikka with Square Numbers &#x1f9c0; 参考题解 &#x1f37b; AC code import java.util.Scanner;public class Main {static boolean isSqu(int x){int t (int) Math.sqrt(x);return t * t x;}public static void main(String[] args…

Vue2:组件基础(上)

Vue2&#xff1a;组件基础&#xff08;上&#xff09; Date: July 29, 2023 Sum: 生命周期、Vue-cli、组件的使用、小黑记账清单、小兔鲜首页 生命周期&#xff1a; 生命周期介绍 思考&#xff1a; 什么时候可以发送初始化渲染请求&#xff1f;&#xff08;越早越好&#x…

Aviator这么丝滑,怎么实现的呢?

大家好&#xff0c;我是老三&#xff0c;在上期 里我们介绍了轻量级规则引擎AviatorScript的基本用法和一些使用案例&#xff0c;这期我们来研究一下&#xff0c;这么丝滑的规则脚本是怎么实现的。 概览 我们先来回顾一个简单的例子&#xff1a; Testpublic void test(){//表…

一道RSA题(忘了名字)-云上贵州-网络安全攻防竞赛个人赛

题目&#xff1a; 很遗憾&#xff0c;这道题当时没做出来。 话不多说&#xff0c;直接开始&#xff0c;题目只给了一个式子&#xff0c;这里就命名为hint&#xff1a; 最开始我的想法是化为模q的形式&#xff0c;也就是&#xff1a; 然后就变成了&#xff1a; 接着就一直卡在这…

国产数据库排行

目录 一、理论 1.国产数据库排行 2.数据 一、理论 1.国产数据库排行 &#xff08;1&#xff09;墨天轮榜单 墨天轮国产数据库流行度排行于2019年6月推出&#xff0c;通过近50个维度的数据来考察近300个国产数据库的流行度排行&#xff0c;每月1日更新排行数据&#xff0c…

js 使用 Object.defineProperty() 对属性进行限制 06

小夏小夏&#xff0c;可爱到爆炸 &#x1f923; &#x1f495;&#x1f495;&#x1f495; 文章目录 一、对属性操作的控制二、属性描述符三、数据属性描述符四、存取属性描述符五、vue2 响应式原理六、defineProerties 同时定义多个属性七、对象方法补充 一、对属性操作的控制…

勘探开发人工智能技术:机器学习(5)

0 提纲 6.1 矩阵分解 6.2 全连接 BP 神经网络 6.3 卷积神经网络 6.4 LSTM 6.5 Transformer 6.6 U-Net 1 矩阵分解 把稀疏矩阵分解成两个小矩阵的乘积, 恢复后的矩阵用于预测. 1.1 基本概念 矩阵分解是使用数学应对机器学习问题的一类典型而巧妙的方法. 矩阵分解是把将一个…

数字万用表测量基础知识--DMM的显示位数

概览 DMM&#xff08;即数字万用表&#xff09;是一种电气测试和测量仪器&#xff0c;可测量直流和交流信号的电压、电流和电阻。本文介绍如何正确使用和理解数字万用表(DMM)。 DMM的显示位数 数字万用表(DMM)可用于进行各种测量。在选择DMM或理解所使用的DMM时&#xff0c;首…

jupyter切换conda虚拟环境

环境安装 conda install nb_conda 进入你想使用的虚拟环境&#xff1a; conda activate your_env_name 在你想使用的conda虚拟环境中&#xff1a; conda install -y jupyter 在虚拟环境中安装jupyter&#xff1a; conda install -y jupyter 重启jupyter 此时我们已经把该安装…

【学习FreeRTOS】第3章——FreeRTOS移植及配置文件

1.FreeRTOS源码简介 【一级目录&#xff1a;/】以下FreeRTOS的源码&#xff0c;其中&#xff0c;FreeRTOS文件夹最为重要&#xff0c;代笔FreeRTOS内核 【二级目录&#xff1a;/FreeRTOS】以下为FreeRTOS文件夹的内容&#xff0c;比较重要的有Demo文件夹和Source文件夹 【三级…

【使用Hilbert变换在噪声信号中进行自动活动检测】基于Hilbert变换和平滑技术进行自动信号分割和活动检测研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

linux文件I/O之 close()、lseek()、read()、write() 函数用法

1. close() 函数 头文件和函数声明 #include <unistd.h> int close(int fd); 函数功能 关闭一个文件描述符 返回值 成功时返回 0。失败则返回 -1&#xff0c;并设置 errno 为相应的错误标志。 参数 fd&#xff1a;文件描述符 说明 像其它所有系统调用一样&…