面试官要不你来讲讲你们对MySQL是怎么调优的?

候选者:哇,这命题很大阿...我认为,对于开发者而言,对MySQL的调优重点一般是在「开发规范」、「数据库索引」又或者说解决线上慢查询上。

候选者:而对于MySQL内部的参数调优,由专业的DBA来搞。

面试官:扯了这么多,你就是想表达你不会MySQL参数调优,对吧

候选者:草,被发现了。

面试官那你来聊聊你们平时开发的规范和索引这块,平时是怎么样的吧。

候选者:嗯,首先,我们在生产环境下,创建数据库表,都是在工单系统下完成的(那就自然需要DBA审批)。如果在创建表时检测到没有创建索引,那就会直接提示warning(:

候选者:理论上来说,如果表有一定的数据量,那就应该要创建对应的索引。从数据库查询数据需要注意的地方还是蛮多的,其中很多都是平时积累来的。比如说:

候选者:1. 是否能使用「覆盖索引」,减少「回表」所消耗的时间。意味着,我们在select 的时候,一定要指明对应的列,而不是select *

候选者:2. 考虑是否组建「联合索引」,如果组建「联合索引」,尽量将区分度最高的放在最左边,并且需要考虑「最左匹配原则」

候选者:3.对索引进行函数操作或者表达式计算会导致索引失效

候选者:4.利用子查询优化超多分页场景。比如 limit offset , n 在MySQL是获取 offset + n的记录,再返回n条。而利用子查询则是查出n条,通过ID检索对应的记录出来,提高查询效率。

面试官:嗯...

候选者:5.通过explain命令来查看SQL的执行计划,看看自己写的SQL是否走了索引,走了什么索引。通过show profile 来查看SQL对系统资源的损耗情况(不过一般还是比较少用到的)

候选者:6.在开启事务后,在事务内尽可能只操作数据库,并有意识地减少锁的持有时间(比如在事务内需要插入&&修改数据,那可以先插入后修改。因为修改是更新操作,会加行锁。如果先更新,那并发下可能会导致多个事务的请求等待行锁释放)

面试官:嗯,你提到了事务,之前也讲过了事务的隔离级别嘛,那你线上用的是什么隔离级别?

候选者:嗯,我们这边用的是Read Commit(读已提交),MySQL默认用的是Repeatable read(可重复读)。选用什么隔离级别,主要看应用场景嘛,因为隔离级别越低,事务并发性能越高。

候选者:(一般互联网公司都选择Read Commit作为主要的隔离级别)

候选者:像Repeatable read(可重复读)隔离级别,就有可能因为「间隙锁」导致的死锁问题。

候选者:但可能你已经知道,MySQL默认的隔离级别为Repeatable read。很大一部分原因是在最开始的时候,MySQL的binlog没有row模式,在read commit隔离级别下会存在「主从数据不一致」的问题

候选者:binlog记录了数据库表结构和表数据「变更」,比如update/delete/insert/truncate/create。在MySQL中,主从同步实际上就是应用了binlog来实现的(:

候选者:有了该历史原因,所以MySQL就将默认的隔离级别设置为Repeatable read

面试官:嗯,那我顺便想问下,你们遇到过类似的问题吗:即便走对了索引,线上查询还是慢。

候选者:嗯嗯,当然遇到过了

面试官那你们是怎么做的?

候选者:如果走对了索引,但查询还是慢,那一般来说就是表的数据量实在是太大了。

候选者:首先,考虑能不能把「旧的数据」给"删掉",对于我们公司而言,我们都会把数据同步到Hive,说明已经离线存储了一份了。

候选者:那如果「旧的数据」已经没有查询的业务了,那最简单的办法肯定是"删掉"部分数据咯。数据量降低了,那自然,检索速度就快了...

面试官:嗯,但一般不会删的

候选者:没错,只有极少部分业务可以删掉数据(:

候选者:随后,就考虑另一种情况,能不能在查询之前,直接走一层缓存(Redis)。

候选者:而走缓存的话,又要看业务能不能忍受读取的「非真正实时」的数据(毕竟Redis和MySQL的数据一致性需要保证),如果查询条件相对复杂且多变的话(涉及各种group by 和sum),那走缓存也不是一种好的办法,维护起来就不方便了...

候选者:再看看是不是有「字符串」检索的场景导致查询低效,如果是的话,可以考虑把表的数据导入至Elasticsearch类的搜索引擎,后续的线上查询就直接走Elasticsearch了。

候选者:MySQL->Elasticsearch需要有对应的同步程序(一般就是监听MySQL的binlog,解析binlog后导入到Elasticsearch)

候选者:如果还不是的话,那考虑要不要根据查询条件的维度,做相对应的聚合表,线上的请求就查询聚合表的数据,不走原表。

候选者:比如,用户下单后,有一份订单明细,而订单明细表的量级太大。但在产品侧(前台)透出的查询功能是以「天」维度来展示的,那就可以将每个用户的每天数据聚合起来,在聚合表就是一个用户一天只有一条汇总后的数据。

候选者:查询走聚合后的表,那速度肯定杠杠的(聚合后的表数据量肯定比原始表要少很多)

候选者:思路大致的就是「以空间换时间」,相同的数据换别的地方也存储一份,提高查询效率

面试官那我还想问下,除了读之外,写性能同样有瓶颈,怎么办?

候选者:你说到这个,我就不困了。

候选者:如果在MySQL读写都有瓶颈,那首先看下目前MySQL的架构是怎么样的。

候选者:如果是单库的,那是不是可以考虑升级至主从架构,实现读写分离。

候选者:简单理解就是:主库接收写请求,从库接收读请求。从库的数据由主库发送的binlog进而更新,实现主从数据一致(在一般场景下,主从的数据是通过异步来保证最终一致性的)

面试官:嗯...

候选者:如果在主从架构下,读写仍存在瓶颈,那就要考虑是否要分库分表了

候选者:至少在我前公司的架构下,业务是区分的。流量有流量数据库,广告有广告的数据库,商品有商品的数据库。所以,我这里讲的分库分表的含义是:在原来的某个库的某个表进而拆分。

候选者:比如,现在我有一张业务订单表,这张订单表在广告库中,假定这张业务订单表已经有1亿数据量了,现在我要分库分表

候选者:那就会将这张表的数据分至多个广告库以及多张表中(:

候选者:分库分表的最明显的好处就是把请求进行均摊(本来单个库单个表有一亿的数据,那假设我分开8个库,那每个库1200+W的数据量,每个库下分8张表,那每张表就150W的数据量)。

面试官你们是以什么来作为分库键的?

候选者:按照我们这边的经验,一般来说是按照userId的(因为按照用户的维度查询比较多),如果要按照其他的维度进行查询,那还是参照上面的的思路(以空间换时间)。

面试官那分库分表后的ID是怎么生成的?

候选者:这就涉及到分布式ID生成的方式了,思路有很多。有借助MySQL自增的,有借助Redis自增的,有基于「雪花算法」自增的。具体使用哪种方式,那就看公司的技术栈了,一般使用Redis和基于「雪花算法」实现用得比较多。

候选者:至于为什么强调自增(还是跟索引是有序有关,前面已经讲过了,你应该还记得)

面试官:嗯,那如果我要分库分表了,迁移的过程是怎么样的呢

候选者:我们一般采取「双写」的方式来进行迁移,大致步骤就是:

候选者:一、增量的消息各自往新表和旧表写一份

候选者:二、将旧表的数据迁移至新库

候选者:三、迟早新表的数据都会追得上旧表(在某个节点上数据是同步的)

候选者:四、校验新表和老表的数据是否正常(主要看能不能对得上)

候选者:五、开启双读(一部分流量走新表,一部分流量走老表),相当于灰度上线的过程

候选者:六、读流量全部切新表,停止老表的写入

候选者:七、提前准备回滚机制,临时切换失败能恢复正常业务以及有修数据的相关程序。

面试官:嗯...今天就到这吧

本文总结:

  • 数据库表存在一定数据量,就需要有对应的索引
  • 发现慢查询时,检查是否走对索引,是否能用更好的索引进行优化查询速度,查看使用索引的姿势有没有问题
  • 当索引解决不了慢查询时,一般由于业务表的数据量太大导致,利用空间换时间的思想
  • 当读写性能均遇到瓶颈时,先考虑能否升级数据库架构即可解决问题,若不能则需要考虑分库分表
  • 分库分表虽然能解决掉读写瓶颈,但同时会带来各种问题,需要提前调研解决方案和踩坑

线上不是给你炫技的地方,安稳才是硬道理。能用简单的方式去解决,不要用复杂的方式

欢迎关注我的微信公众号【Java3y】来聊聊Java面试,对线面试官系列持续更新中!

【对线面试官-移动端】系列 一周两篇持续更新中!

【对线面试官-电脑端】系列 一周两篇持续更新中!

原创不易!!求三连!!

面试官问我MySQL调优,我真的是的更多相关文章

  1. 面试官问我JVM调优,我忍不住了!

    面试官:今天要不来聊聊JVM调优相关的吧? 面试官:你曾经在生产环境下有过调优JVM的经历吗? 候选者:没有 面试官:... 候选者:嗯...是这样的,我们一般优化系统的思路是这样的 候选者:1. 一 ...

  2. 面试总问的jvm调优到底是要干什么?

    1. 压力测试的理解,xxx的性能10w/s,对你有意义么? 没有那家卖瓜的会说自己家的不甜,同样,没有哪个开源项目愿意告诉你在对它条件最苛刻的时候压力情况是多少,一般官网号称给你看的性能指标都是在最 ...

  3. 面试官问我MySQL索引,我

    面试官:我看你简历上写了MySQL,对MySQL InnoDB引擎的索引了解吗? 候选者:嗯啊,使用索引可以加快查询速度,其实上就是将无序的数据变成有序(有序就能加快检索速度) 候选者:在InnoDB ...

  4. 面试官问你MySQL的优化,看这篇文章就够了

    作者:zhangqh segmentfault.com/a/1190000012155267 一.EXPLAIN 做MySQL优化,我们要善用 EXPLAIN 查看SQL执行计划. 下面来个简单的示例 ...

  5. 面试官问我,为什么老司机建议MySQL列属性尽量用 NOT NULL ?

    本文阅读时间大约6分钟. 其实写这篇文章,也是来自一个知识星球读者的提问,他在二面的过程中被问到了,由于他简历中写道有 MySQL 调优经验,但这个问题没有回答好,二面被刷了. 其实我们刚学习 C 语 ...

  6. 【MySQL】面试官问我:MySQL如何实现无数据插入,有数据更新?我是这样回答的!

    写在前面 马上就是金九银十的跳槽黄金期了,很多读者都开始出去面试了.这不,又一名读者出去面试被面试官问了一个MySQL的问题:向MySQL中插入数据,如何实现MySQL中没有当前id标识的数据时插入数 ...

  7. 面试官问我,Redis分布式锁如何续期?懵了。

    前言 上一篇[面试官问我,使用Dubbo有没有遇到一些坑?我笑了.]之后,又有一位粉丝和我说在面试过程中被虐了.鉴于这位粉丝是之前肥朝的粉丝,而且周一又要开启新一轮的面试,为了回馈他长期以来的支持,所 ...

  8. 面试官问,说一个你在工作非常有价值的bug

    如果你去参考面试,做足了准备,面对面试官员从容不迫,吐沫横飞的大谈自己的工作经历.突然,面试官横插一句:说一个你在工作非常有价值的bug.顿时,整个空气都仿佛都凝固了!“What?”... 我想没几个 ...

  9. 面试官问:JS的this指向

    前言 面试官出很多考题,基本都会变着方式来考察this指向,看候选人对JS基础知识是否扎实.读者可以先拉到底部看总结,再谷歌(或各技术平台)搜索几篇类似文章,看笔者写的文章和别人有什么不同(欢迎在评论 ...

随机推荐

  1. uni-app 小程序从零开始的开发流程

    前言 本文基于 HBuilderX 3.1.22 + 微信开发者工具 1.05.2106300为主要内容进行说明. 文档版本:1.0.0 更新时间:2021-09-03 15:32 一.准备 uni- ...

  2. HCNP Routing&Switching之OSPF外部路由类型以及forwarding address

    前文我们了解了OSPF的4类.5类LSA,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/15222969.html:今天我们来聊一聊外部路由类型和forward ...

  3. .ssh/config 常用配置

    不用每次都 -i 指定密钥,且避免连接自动断开 ControlMaster auto ControlPath ~/.ssh/connection-%r@%h:%p ControlPersist 4h ...

  4. Docker编排工具Docker Compose的使用

    一.安装docker compose 官网推荐方式之一: sudo curl -L "https://github.com/docker/compose/releases/download/ ...

  5. Linux(二)——常用命令

    一.一般指令 立刻关机:shutdown -h now 1分钟后关机:shutdown -h 1 立刻重启:shutdown -r now 立刻关机:halt 立刻重启:reboot 把内存的数据同步 ...

  6. 手把手教你 Docker Compose的安装和使用

    一.Docker Compose是什么? Docker Compose是一个工具,用于定义和运行多容器应用程序的工具: Docker Compose通过yml文件定义多容器的docker应用: Doc ...

  7. Git:为Git Bash.exe设置默认起始目录的两种方式(start in、~/.bashrc)

    在协作开发的过程中,我们经常要进行一些项目的上传拉取操作. 在无数次不厌其烦的打开关闭 Git Bash 后,我实在忍受不了作为一个程序员还要每次都要进行如下的小白操作了 cd /d/my-proje ...

  8. Excel表格中单击一个单元格如何将整行整列变色

    视图->阅读模式 开启阅读模式后 就会显示如下情景,是的你点击任意单元格后,显示整行/整列

  9. 合并区间 leetcode

    描述: 给出一组区间,请合并所有重叠的区间. 请保证合并后的区间按区间起点升序排列. 输入: [[10,30],[20,60],[80,100],[150,180]] 输出: [[10,60],[80 ...

  10. TP5关联模型出现疑问,待解决

    一对一: hasOne('关联模型名','外键名','主键名',['模型别名定义'],'join类型'); 说明:其他模型一对一都可以按照手册说明写,但上面代码只能这么写才能执行正确答案, 如果是 / ...