MySQL面试知识点追命连环问(二)事务、索引及SQL优化

上次我们讨论了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标准中定义了四种隔离级别,并规定了每种隔离级别下上述几个问题是否存在。

一般来说,隔离级别越低,系统开销越低,可支持的并发越高,但隔离性也越差。隔离级别与读问题的关系如下:

image

读未提交:脏读,不可重复读,幻读都有可能发生
读已提交:不可重复读,幻读可能发生
可重复读:幻读可能发生
可串行化:都不可能发生

在实际应用中,读未提交在并发时会导致很多问题,而性能相对于其他隔离级别提高却很有限,因此使用较少。

可串行化强制事务串行,并发效率很低,只有当对数据一致性要求极高且可以接受没有并发时使用,因此使用也较少。

因此在大多数数据库系统中,默认的隔离级别是读已提交(如Oracle)或可重复读。

MySQL事务默认的隔离级别是可重复读,而且MySQL可以解决了幻读的问题。

面试官:看来你对事务理解的还不错。那你知道MySQL的另一个重要特性索引吗?

2. MySQL索引

答:索引就是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。索引的实现通常使用B树及其变种B+树。

在数据之外,数据库维护这些原来快速查找的索引也是要付出代价的。一是增加了数据库的存储,二是在插入和修改数据时要花费较多的时间(因为索引也要随之变动)。

面试官:那索引是怎样实现的呢?MyISAM和Innodb的实现方式一样吗?

答:不一样的。MyISAM和Innodb虽然都使用B+树作为索引结构,但索引的实现方式还是不一样的。

MyISAM的叶节点的data域存放的是数据记录的地址,而Innodb数据文件本身就是索引文件。

MyISAM中索引检索的算法为首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,则取出其data域的值,然后以data域的值为地址,读取相应数据记录。

image

而在InnoDB中,表数据文件本身就是按B+Tree组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引。

image

因为InnoDB的数据文件本身要按主键聚集,所以InnoDB要求表必须有主键(MyISAM可以没有)。

如果没有显式指定,则MySQL系统会自动选择一个可以唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL自动为InnoDB表生成一个隐含字段作为主键。

B+树是一种B树的变种,为有序数组链表+平衡多叉树。基本和B树类似,只有叶子节点存放数据,而且叶子节点之间通过指针相连。

面试官:那为什么索引用B+树呢,B+树有什么优点呢?

1、B+树的磁盘读写代价更低: B+树的内部节点并没有指向关键字具体信息的指针,因此其内部节点相对B树更小,如果把所有同一内部节点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多,一次性读入内存的需要查找的关键字也就越多,相对IO读写次数就降低了。

2、由于B+树的数据都存储在叶子结点中,分支结点均为索引,方便扫库,只需要扫一遍叶子结点即可,但是B树因为其分支结点同样存储着数据,我们要找到具体的数据,需要进行一次中序遍历按序来扫,所以B+树更加适合在区间查询的情况,所以通常B+树用于数据库索引。

image

面试官:那什么是聚簇索引呢?

聚簇索引是一种数据存储方式,它实际上是在同一个结构中保存了B+树索引和数据行,InnoDB表是按照聚簇索引组织的。
InnoDB通过主键聚簇数据。他使用主键值的大小来进行记录和页的排序。叶子节点存储的是完整的用户记录。

注:聚簇索引不需要我们显示的创建,他是由InnoDB存储引擎自动为我们创建的。如果没有主键,其也会默认创建一个。

但聚簇索引只有在搜索条件为主键是才发挥作用,如果为其他的字段就不行,这个时候就需要普通索引了。

二级索引的叶子节点不再是完整的数据记录,而是字段和主键值。当需要这条记录的其他字段时仍然需要根据这个主键id去查询,这个步骤叫做回表。

聚簇索引表最大限度地提高了I/O密集型应用的性能,但它也有以下几个限制:

  1. 插入速度严重依赖于插入顺序,按照主键的顺序插入是最快的方式,否则将会出现页分裂,严重影响性能。因此,对于InnoDB表,我们一般都会定义一个自增的ID列为主键。

  2. 更新主键的代价很高,因为将会导致被更新的行移动。因此,对于InnoDB表,我们一般定义主键为不可更新的。

  3. 二级索引访问需要两次索引查找,第一次找到主键值,第二次根据主键值找到行数据。

面试官:索引有哪些类型?索引越多越好吗?

除了上面说的主键索引和普通索引,还有唯一索引,联合索引和全文索引。

唯一索引:该列具有唯一性的同时又是索引,不允许重复。
全文索引:主要用于文本的查询,它的出现是为了解决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进行分析。常见慢查询主要有以下几种情况:

  1. 索引没起作用。字段没建立索引,或者是索引没有起作用。使用了like关键字或使用了多列索引的查询语句。

  2. 数据库结构不合理。合理的数据库结构不仅可以使数据库占用更小的磁盘,也可以让sql执行速度更快。一可以将字段很多的表拆解成多个表。二增加中间表。

  3. 分解关联查询。将大查询分成多个小查询。

  4. 优化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;

好啦,今天的追命连环问就到这里了,下次继续,如对文章有疑惑或补充的地方欢迎留言交流(●'◡'●)。原创不易,如果对你有帮助的话欢迎点赞!

相关推荐阅读

你知道一次完整的HTTP请求过程吗

Redis常见面试题连环问,你能回答到第几问?****(上)

大厂高频面试题:****高并发下接口幂等性的解决方案?

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • 这篇文章主要涉及到MySQL的知识点: 索引(包括分类及优化方式,失效条件,底层结构) sql语法(join,un...
    一根薯条阅读 2,695评论 0 8
  • 索引 数据库中的查询操作非常普遍,索引就是提升查找速度的一种手段 索引的类型 从数据结构角度分 1.B+索引:传统...
    一凡呀阅读 2,853评论 0 8
  • MySQL技术内幕:SQL编程 姜承尧 第1章 SQL编程 >> B是由MySQL创始人之一Monty分支的一个版...
    沉默剑士阅读 2,404评论 0 3
  • 据现在的天文学家和相关科学家研究推测,太阳系已经存在了大约46亿年,而银河系大致存在了130亿年。而银河系在...
    润树阅读 332评论 1 5
  • 记忆里那人从未穿过红衣,今日的一身红也是她意料中的俊美非凡,举手投足中都气质尽显,果然非池中物,莫晚笑了笑。 “阿...
    勋岛阅读 152评论 0 0