MySQL面试知识点追命连环问(二)事务、索引及SQL优化
ccwgpt 2024-11-25 10:23 71 浏览 0 评论
目录
1. MySQL事务
2. MySQL索引
3. SQL优化
4.常见问题
上次我们讨论了MySQL的运行流程及原理,字段设计,存储引擎和查询缓存。
MySQL面试知识点追命连环问(一)
这次我们继续来追命连环问关于事务,索引,SQL优化等相关的内容。准备好了吗?
- 事务
- 索引
- SQL优化
- 常见问题
1. MySQL事务
面试官:你知道事务吗?
我:知道。事务(Transaction)是访问和更新数据库的程序执行单元;
事务中可能包含一个或多个sql语句,这些语句要么都执行,要么都不执行。
事务主要有四大特性。即ACID:原子性,一致性,隔离性和持久性。
原子性:不可分割的操作单元,事务中所有操作,要么全部成功;要么回滚到执行事务之前的状态。
一致性:在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。
隔离性:事务操作之间彼此独立和透明互不影响。如果一个事务处理后的结果,影响了其他事务,那么其他事务会撤回。
持久性:事务一旦提交,其结果就是永久的。即便发生系统故障,也能恢复。
面试官:嗯四大特性说的没错,那你知道高并发场景下事务可能会出现的问题吗?
我:事务并发执行的话确实会产生一些问题。比如说:幻读,脏读,不可重复读。因为隔离性脏写是不会发生的。
脏读:一个事务读取到另一个未提交事务修改的数据。
session A:查询,得到某条数据
session B:修改某条数据,但是最后回滚掉啦
session A:在sessionB修改某条数据之后,在回滚之前,读取了该条记录
对于session A来说,读到了session回滚之前的脏数据
不可重复读:多次读取的数据内容不一样。
session A:查询某条记录
session B : 修改该条记录,并提交事务
session A : 再次查询该条记录,发现前后查询不一致
幻读:前后多次读取,数据总量不一样。
session A:查询表内所有记录
session B : 新增一条记录,并查询表内所有记录
session A : 再次查询该条记录,发现前后查询不一致
面试管:那什么情况下会出现这些问题呢?
MySQL标准中定义了四种隔离级别,并规定了每种隔离级别下上述几个问题是否存在。
一般来说,隔离级别越低,系统开销越低,可支持的并发越高,但隔离性也越差。隔离级别与读问题的关系如下:
?
读未提交:脏读,不可重复读,幻读都有可能发生
读已提交:不可重复读,幻读可能发生
可重复读:幻读可能发生
可串行化:都不可能发生
在实际应用中,读未提交在并发时会导致很多问题,而性能相对于其他隔离级别提高却很有限,因此使用较少。
可串行化强制事务串行,并发效率很低,只有当对数据一致性要求极高且可以接受没有并发时使用,因此使用也较少。
因此在大多数数据库系统中,默认的隔离级别是读已提交(如Oracle)或可重复读。
MySQL事务默认的隔离级别是可重复读,而且MySQL可以解决了幻读的问题。
面试官:看来你对事务理解的还不错。那你知道MySQL的另一个重要特性索引吗?
2. MySQL索引
答:索引就是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。索引的实现通常使用B树及其变种B+树。
在数据之外,数据库维护这些原来快速查找的索引也是要付出代价的。一是增加了数据库的存储,二是在插入和修改数据时要花费较多的时间(因为索引也要随之变动)。
面试官:那索引是怎样实现的呢?MyISAM和Innodb的实现方式一样吗?
答:不一样的。MyISAM和Innodb虽然都使用B+树作为索引结构,但索引的实现方式还是不一样的。
MyISAM的叶节点的data域存放的是数据记录的地址,而Innodb数据文件本身就是索引文件。
MyISAM中索引检索的算法为首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,则取出其data域的值,然后以data域的值为地址,读取相应数据记录。
?
MyISAM索引
而在InnoDB中,表数据文件本身就是按B+Tree组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引。
?
Innodb索引
因为InnoDB的数据文件本身要按主键聚集,所以InnoDB要求表必须有主键(MyISAM可以没有)。
如果没有显式指定,则MySQL系统会自动选择一个可以唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL自动为InnoDB表生成一个隐含字段作为主键。
B+树是一种B树的变种,为有序数组链表+平衡多叉树。基本和B树类似,只有叶子节点存放数据,而且叶子节点之间通过指针相连。
面试官:那为什么索引用B+树呢,B+树有什么优点呢?
1、 B+树的磁盘读写代价更低:B+树的内部节点并没有指向关键字具体信息的指针,因此其内部节点相对B树更小,如果把所有同一内部节点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多,一次性读入内存的需要查找的关键字也就越多,相对IO读写次数就降低了。
2、由于B+树的数据都存储在叶子结点中,分支结点均为索引,方便扫库,只需要扫一遍叶子结点即可,但是B树因为其分支结点同样存储着数据,我们要找到具体的数据,需要进行一次中序遍历按序来扫,所以B+树更加适合在区间查询的情况,所以通常B+树用于数据库索引。
?
面试官:那什么是聚簇索引呢?
聚簇索引是一种数据存储方式,它实际上是在同一个结构中保存了B+树索引和数据行,InnoDB表是按照聚簇索引组织的。
InnoDB通过主键聚簇数据。他使用主键值的大小来进行记录和页的排序。叶子节点存储的是完整的用户记录。
注:聚簇索引不需要我们显示的创建,他是由InnoDB存储引擎自动为我们创建的。如果没有主键,其也会默认创建一个。
但聚簇索引只有在搜索条件为主键是才发挥作用,如果为其他的字段就不行,这个时候就需要普通索引了。
二级索引的叶子节点不再是完整的数据记录,而是字段和主键值。当需要这条记录的其他字段时仍然需要根据这个主键id去查询,这个步骤叫做回表。
聚簇索引表最大限度地提高了I/O密集型应用的性能,但它也有以下几个限制:
- 插入速度严重依赖于插入顺序,按照主键的顺序插入是最快的方式,否则将会出现页分裂,严重影响性能。因此,对于InnoDB表,我们一般都会定义一个自增的ID列为主键。
- 更新主键的代价很高,因为将会导致被更新的行移动。因此,对于InnoDB表,我们一般定义主键为不可更新的。
- 二级索引访问需要两次索引查找,第一次找到主键值,第二次根据主键值找到行数据。
面试官:索引有哪些类型?索引越多越好吗?
除了上面说的主键索引和普通索引,还有唯一索引,联合索引和全文索引。
唯一索引:该列具有唯一性的同时又是索引,不允许重复。
全文索引:主要用于文本的查询,它的出现是为了解决WHERE name LIKE “%word%"这类针对文本的模糊查询效率较低的问题。
联合索引:对多列值进行一个索引,其效率大于索引合并。需遵循前缀原则。
建索引是有开销的所以也不是越多越好,只要在需要的字段上建立索引。
第一,创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。
第二,索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。
第三,当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。
索引的使用需要注意以下几点:
1.最左前缀原则。一个联合索引(a,b,c),如果有一个查询条件有a,有b,那么他则走索引,如果有一个查询条件没有a,那么他则不走索引。
2.使用唯一索引。具有多个重复值的列,其索引效果最差。
3.不要过度索引。每个额外的索引都要占用额外的磁盘空间,并降低写操作的性能。在修改表的内容时,索引必须进行更新,有时可能需要重构,因此,索引越多,所花的时间越长。
4、索引列不能参与计算,保持列“干净”,比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很简单,b+树中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本太大。所以语句应该写成create_time = unix_timestamp(’2014-05-29’);
5.一定要设置一个主键。前面聚簇索引说到如果不指定主键,InnoDB会自动为其指定主键,这个我们是看不见的。反正都要生成一个主键的,还不如我们设置,以后在某些搜索条件时还能用到主键的聚簇索引。
6.主键推荐用自增id,而不是uuid。上面的聚簇索引说到每页数据都是排序的,并且页之间也是排序的,如果是uuid,那么其肯定是随机的,其可能从中间插入,导致页的分裂,产生很多表碎片。如果是自增的,那么其有从小到大自增的,有顺序,那么在插入的时候就添加到当前索引的后续位置。当一页写满,就会自动开辟一个新的页。
索引禁忌:
- 不在低区分度的列上建?索引,例如“性别”
- 尽量避免%前导的查询,如like “%ab”
- 尽量避免负向查询,如not in/like
- 避免全表扫描和频繁的回表操作
面试官:看来你对索引掌握的很不错啊,那你平常遇到慢查询是怎么优化的呢?
3. SQL优化
SQL语句从客户端经由网络协议到查询缓存,如果没有命中缓存,再经过解析工作,得到准确的SQL然后再来到优化器。
首先,我们知道每一条SQL都有不同的执行方法,要不通过索引,要不通过全表扫描的方式。
影响SQL速度的主要在I/O成本和CPU成本的消耗上。
数据存储在硬盘上,我们想要进行某个操作需要将其加载到内存中,这个过程的时间被称为I/O成本。在内存对结果集进行排序的时间被称为CPU成本。
所以进行sql优化首先进行索引优化,让我们的sql语句尽量走索引而不是走全表扫描的方法。
在平常遇到慢查询时首先去分析慢查询日志,找出慢查询的sql。然后针对这些sql进行分析。常见慢查询主要有以下几种情况:
- 索引没起作用。字段没建立索引,或者是索引没有起作用。使用了like关键字或使用了多列索引的查询语句。
- 数据库结构不合理。合理的数据库结构不仅可以使数据库占用更小的磁盘,也可以让sql执行速度更快。一可以将字段很多的表拆解成多个表。二增加中间表。
- 分解关联查询。将大查询分成多个小查询。
- 优化limit分页。当偏移量非常大时会导致前面查询到的无用数据都要舍弃掉,如果表非常大,且筛选字段没有合适的索引,那么这样的代价是非常高的。如我们下一次的查询能从前一次查询结束后标记的位置开始查找,那将节省很多开销。
4.常见问题
问题一:嗯现在我们来看看具体问题,那你看这条语句会用到索引吗?
以下语句是否会应用索引:SELECT FROM users WHERE YEAR(adddate) < 2007;
答:不会,因为只要列涉及到运算,MySQL就不会使用索引。
问题二:那如果列值为NULL时,查询是否会用到索引?
在MySQL里NULL值的列也是走索引的。当然,如果计划对列进行索引,就要尽量避免把它设置为可空,MySQL难以优化引用了可空列的查询,它会使索引、索引统计和值更加复杂。
问题三:索引一定会提高速度吗?
通常,通过索引查询数据比全表扫描要快。但是我们也必须注意到它的代价。
索引需要空间来存储,也需要定期维护, 每当有记录在表中增减或索引列被修改时,索引本身也会被修改. 这意味着每条记录的INSERT,DELETE,UPDATE将为此多付出4,5 次的磁盘I/O. 因为索引需要额外的存储空间和处理,那些不必要的索引反而会使查询反应时间变慢。使用索引查询不一定能提高查询性能。
问题四:如何查询第n高的工资?
SELECT DISTINCT(salary) from employee ORDER BY salary DESC LIMIT n-1,1
问题五:一个6亿的表a,一个3亿的表b,通过外间tid关联,你如何最快的查询出满足条件的第50000到第50200中的这200条数据记录。
1、如果A表TID是自增长,并且是连续的,B表的ID为索引
select * from a,b where a.tid = b.id and a.tid>500000 limit 200;
2、如果A表的TID不是连续的,那么就需要使用覆盖索引。TID要么是主键,要么是辅助索引,B表ID也需要有索引。
select * from b , (select tid from a limit 50000,200) a where b.id = a .tid;
好啦,今天的追命连环问就到这里了,下次继续,如对文章有疑惑或补充的地方欢迎留言交流(●'?'●)。原创不易,如果对你有帮助的话欢迎点赞!
?
相关推荐
- 一个基于.Net Core遵循Clean Architecture原则开源架构
-
今天给大家推荐一个遵循CleanArchitecture原则开源架构。项目简介这是基于Asp.netCore6开发的,遵循CleanArchitecture原则,可以高效、快速地构建基于Ra...
- AI写代码翻车无数次,我发现只要提前做好这3步,bug立减80%
-
写十万行全是bug之后终于找到方法了开发"提示词管理助手"新版本那会儿,我差点被bug整崩溃。刚开始两周,全靠AI改代码架构,结果十万行程序漏洞百出。本来以为AI说没问题就稳了,结果...
- OneCode低代码平台的事件驱动设计:架构解析与实践
-
引言:低代码平台的事件驱动范式在现代软件开发中,事件驱动架构(EDA)已成为构建灵活、松耦合系统的核心范式。OneCode低代码平台通过创新性的注解驱动设计,将事件驱动理念深度融入平台架构,实现了业务...
- 国内大厂AI插件评测:根据UI图生成Vue前端代码
-
在IDEA中安装大厂的AI插件,打开ruoyi增强项目:yudao-ui-admin-vue31.CodeBuddy插件登录腾讯的CodeBuddy后,大模型选择deepseek-v3,输入提示语:...
- AI+低代码技术揭秘(二):核心架构
-
本文档介绍了为VTJ低代码平台提供支持的基本架构组件,包括Engine编排层、Provider服务系统、数据模型和代码生成管道。有关UI组件库和widget系统的信息,请参阅UI...
- GitDiagram用AI把代码库变成可视化架构图
-
这是一个名为gitdiagram的开源工具,可将GitHub仓库实时转换为交互式架构图,帮助开发者快速理解代码结构。核心功能一键可视化:替换GitHubURL中的"hub...
- 30天自制操作系统:第六天:代码架构整理与中断处理
-
1.拆开bootpack.c文件。根据设计模式将对应的功能封装成独立的文件。2.初始化pic:pic(可编程中断控制器):在设计上,cpu单独只能处理一个中断。而pic是将8个中断信号集合成一个中断...
- AI写代码越帮越忙?2025年研究揭露惊人真相
-
近年来,AI工具如雨后春笋般涌现,许多人开始幻想程序员的未来就是“对着AI说几句话”,就能轻松写出完美的代码。然而,2025年的一项最新研究却颠覆了这一期待,揭示了一个令人意外的结果。研究邀请了16位...
- 一键理解开源项目:两个自动生成GitHub代码架构图与说明书工具
-
一、GitDiagram可以一键生成github代码仓库的架构图如果想要可视化github开源项目:https://github.com/luler/reflex_ai_fast,也可以直接把域名替换...
- 5分钟掌握 c# 网络通讯架构及代码示例
-
以下是C#网络通讯架构的核心要点及代码示例,按协议类型分类整理:一、TCP协议(可靠连接)1.同步通信//服务器端usingSystem.Net.Sockets;usingTcpListene...
- 从复杂到优雅:用建造者和责任链重塑代码架构
-
引用设计模式是软件开发中的重要工具,它为解决常见问题提供了标准化的解决方案,提高了代码的可维护性和可扩展性,提升了开发效率,促进了团队协作,提高了软件质量,并帮助开发者更好地适应需求变化。通过学习和应...
- 低代码开发当道,我还需要学习LangChain这些框架吗?| IT杂谈
-
专注LLM深度应用,关注我不迷路前两天有位兄弟问了个问题:当然我很能理解这位朋友的担忧:期望效率最大化,时间用在刀刃上,“不要重新发明轮子”嘛。铺天盖地的AI信息轰炸与概念炒作,很容易让人浮躁与迷茫。...
- 框架设计并不是简单粗暴地写代码,而是要先弄清逻辑
-
3.框架设计3.框架设计本节我们要开发一个UI框架,底层以白鹭引擎为例。框架设计的第一步并不是直接撸代码,而是先想清楚设计思想,抽象。一个一个的UI窗口是独立的吗?不是的,...
- 大佬用 Avalonia 框架开发的 C# 代码 IDE
-
AvalonStudioAvalonStudio是一个开源的跨平台的开发编辑器(IDE),AvalonStudio的目标是成为一个功能齐全,并且可以让开发者快速使用的IDE,提高开发的生产力。A...
- 轻量级框架Lagent 仅需20行代码即可构建自己的智能代理
-
站长之家(ChinaZ.com)8月30日消息:Lagent是一个专注于基于LLM模型的代理开发的轻量级框架。它的设计旨在简化和提高这种模型下代理的开发效率。LLM模型是一种强大的工具,可以...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- 框架图 (58)
- flask框架 (53)
- quartz框架 (51)
- abp框架 (47)
- springmvc框架 (49)
- 分布式事务框架 (65)
- scrapy框架 (56)
- shiro框架 (61)
- 定时任务框架 (56)
- java日志框架 (61)
- mfc框架 (52)
- abb框架断路器 (48)
- beego框架 (52)
- java框架spring (58)
- grpc框架 (65)
- tornado框架 (48)
- 前端框架bootstrap (54)
- orm框架有哪些 (51)
- 知识框架图 (52)
- ppt框架 (55)
- 框架图模板 (59)
- 内联框架 (52)
- cad怎么画框架 (58)
- ssm框架实现登录注册 (49)
- oracle字符串长度 (48)