当前位置: 首页 > 后端技术 > Java

面试官问我MySQL调优,我真的是

时间:2023-04-01 18:54:47 Java

面试官:你说说你是怎么调MySQL的?考生:哇哦,这是一个很大的命题。。。我觉得对于开发者来说,MySQL调优的重点一般在“开发规范”、“数据库索引”或者解决线上慢查询。考生:MySQL内部的参数调优,专业的DBA应该会做。面试官:说了那么多,就是想表达你不知道怎么调MySQL的参数是吗?考生:草,被发现了。面试官:那么说一下你们平时制定的规范和指标,平时是怎么样的。应聘者:嗯,首先我们在生产环境创建数据库表,都是在工单系统下完成的(那自然要DBA审批)。如果创建表时检测到没有创建索引,则直接提示警告(:考生:理论上,如果表有一定的数据量,那么应该创建相应的索引。注意从数据库查询数据的地方还是挺多的,很多都是平时积累的,比如:考生:1.能不能用“覆盖索引”来减少“回表”消耗的时间,意思是说我们在select的时候,一定要指定对应的列,而不是select*Candidates:2.考虑是否建“联合索引”,如果建“联合索引”,尽量把差异化程度最高的放在最左边,而需要考虑“最左匹配原则”的考生:3、对索引进行函数运算或表达式计算,会导致索引失败n项,使用子查询就是找出n项,通过ID检索对应的记录来提高查询效率。面试官:嗯……考生:5、用explain命令查看SQL执行计划,看你写的是什么SQL索引是否被使用,使用了什么索引。使用showprofile查看SQL对系统资源的消耗(不过一般比较少用)。考生:6、启动事务后,尽量只操作数据库,有意识地减少锁持有时间(比如事务中需要插入&&修改数据,可以先插入再修改。因为修改是更新操作,会加行锁。如果先更新,并发请求可能会导致多个事务请求等待行锁释放)面试官:嗯,你提到了事务,之前也谈到了事务的隔离级别。你在网上使用什么样的隔离?等级?考生:嗯,我们使用的是ReadCommit(已提交读),而MySQL默认使用的是Repeatableread(可重复读)。隔离级别的选择主要看应用场景,因为隔离级别越低,事务并发性能越高。考生:(一般互联网公司选择ReadCommit作为主要隔离级别)考生:和Repeatableread(可重复读)隔离级别一样,可能会出现“间隙锁”导致的死锁问题。考生:但是你可能已经知道MySQL默认的隔离级别是Repeatableread。很大一部分原因是一开始MySQL的binlog没有行模式,在readcommit隔离级别下会出现“主从数据不一致”的问题。考生:binlog记录数据库表结构和表数据的“变化”,如update/delete/insert/truncate/create。在MySQL中,主从同步其实是通过应用binlog来实现的(:考生:由于这个历史原因,MySQL将默认的隔离级别设置为Repeatableread面试官:嗯,那我顺便问一下,有没有遇到过类似问题:即使你走对了索引,在线查询还是慢应试者:嗯,当然遇到面试官:那你怎么做呢?应聘者:如果你走对了索引,但是查询还是慢,一般来说是表数据量太大考生:首先考虑“旧数据”是否可以“删除”,对于我们公司来说,我们会将数据同步到Hive,说明有一份被离线存储了候选人:如果“旧数据”没有查询业务,最简单的方法就是“删除”部分数据减少数据量是的,当然检索速度会更快...面试官:嗯,但是一般不会删考生:可以,只有极少数业务可以删除数据(:考生:那再考虑另外一种情况,能不能直接上一层缓存(Redis)再查询。考生:如果使用缓存,看业务能不能容忍“非实时”的数据读取(毕竟需要保证Redis和MySQL的数据一致性),如果查询条件比较复杂且多变(涉及到各种Groupby和sum),那么缓存就不是一个好办法,而且不方便维护……考生:检查是否存在“字符串”的检索场景导致查询效率低下。如果是这样,可以考虑将表中的数据导入Elasticsearch等搜索引擎,后续在线查询会直接进入Elasticsearch。候选:MySQL->Elasticsearch需要有相应的同步程序(一般是监控MySQL的binlog,解析binlog导入Elasticsearch)聚合表,在线请求查询的是聚合表中的数据,而不是原始表中的数据。考生:比如用户下单后,有一个订单明细,但是订单明细的量级太大。而暴露在产品端(前台)的查询功能是在“天”维度展示的,所以可以汇总每个用户每天的数据。在聚合表中,每个用户每天只有一个聚合数据。考生:查询聚合表,速度肯定是快的(聚合表的数据量肯定比原表少很多)考生:大意是“以空间换时间”,同样的数据换成other也在本地存一份,提高查询效率面试官:那我想问一下,除了读,写性能也有瓶颈,怎么办?应聘者:你一提这个,我就不困了。考生:如果MySQL读写有瓶颈,先看看目前的MySQL架构。考生:如果是单库,能不能考虑升级成主从架构,实现读写分离。考生:简单理解就是:主库接收写请求,从库接收读请求。从库的数据通过主库发送的binlog来更新,实现主从数据的一致性(一般场景下,主从数据是异步的,保证最终的一致性)面试官:嗯...应试者:如果master-slave架构下,读写还是有瓶颈,所以要考虑分库分表。应聘者:至少在我之前公司的架构下,业务是差异化的。流量有流量库,广告有广告库,商品有商品库。所以我这里说的分库分表的意思是:把某个原库中的一个表拆分出来。考生:比如我现在有一个业务订单表,这个订单表在广告库中。假设这张业务订单表已经有1亿条数据,现在我要分库分表考生:那我将这张表的数据分到多个广告库和表中(:考生:分库分表的好处最明显-分库分表是为了平摊请求(本来单库单表有1亿数据,假设我分了8个库,每个库数据量1200+W,每个库分8个表,每张表数据量150W)面试官:你分库key用什么?考生:根据我们的经验,一般是根据userId(因为基于用户维度的查询比较多).如果想基于其他维度查询,参考上面的思路(用空间换时间)面试官:分库分表后ID是怎么生成的考生:这个涉及到分布式ID生成的方式.有很多想法。有的使用MySQL自增,有的使用Redis自增,还有的是基于“雪花算法”自增,具体采用哪种方式,看公司的技术栈,一般Redis和“雪花算法”用的比较多考生:至于为什么要强调自增(还是和索引顺序相关,我之前已经提过,大家应该记得)面试官:嗯,如果我要分库和表,迁移过程是怎样的?考生:我们一般采用“双写”的方式来进行迁移,一般步骤是:考生:1.将增量消息分别写入新表和旧表的副本.考生:2.将旧表中的数据迁移到新数据库中,数据会赶上旧表(数据同步在某个节点上)考生:4.检查新表中的数据是否和旧表正常(主要是看能不能匹配上)候选:5.开启双读(部分流量走新表,部分流量走旧表),相当于流程在灰度中上网,临时切换失败可以恢复正常业务和相关程序进行数据修复。面试官:嗯……今天先说说索引,能不能用更好的索引来优化查询速度,看看使用索引的姿势有没有问题。当索引不能解决慢查询时,一般是业务表数据量大造成的。以空间换时间的思路应该是读当写性能遇到瓶颈时,首先考虑是否可以通过升级数据库架构来解决问题。如果不是,则需要考虑分库分表分库分表。读写的瓶颈虽然可以解决,但是同时会带来各种各样的问题。需要提前研究解决方案,踩坑线不是你炫技的地方,稳定才是硬道理。可以用简单的方法解决,不用复杂的方法。欢迎关注我的微信公众号【Java3y】聊聊Java面试。在线面试官系列持续更新中!【在线面试官-手机版】系列,每周两篇,持续更新中!【在线面试官-电脑】系列每周两篇持续更新中!原创不易!!一连求三!!