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

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

时间:2023-04-01 23:07:38 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来的(因为有很多查询是基于user'sdimension).如果想基于其他维度查询,还是参考上面的思路(用空间换时间)。面试官:分库分表后ID是怎么生成的?考生:这个涉及到分布式ID生成的方式,有很多思路。有的用mysql自增,有的用redis自增,有的基于“雪花算法”自增。使用哪种方法取决于公司的技术栈。一般用的比较多的是Redis和“雪花算法”。应聘者:至于为什么要强调自增(还是和索引的顺序有关,我已经讲过了,你应该记住了)面试官:嗯,如果我要分库分表,什么迁移过程是怎样的?考生:我们一般采用“双写”的方式进行迁移。大致的步骤是:考生:1.将增量消息分别写一份到新表和旧表。考生:2.将旧表中的数据写入迁移到新数据库的考生:3.新表中的数据迟早会赶上旧表(数据在某个节点同步)。考生:4.查看新表和旧表数据是否正常(主要看Canyoumatch)考生:5.开启双读(一部分流量到新表,一部分流量到旧表),相当于上线的过程考生:6.把所有读流量切到新表,停止老表写考生:7.提前准备好回滚机制,临时切换失败后恢复正常业务,并有相关的数据修复程序。面试官:嗯。。。今天就到这里。请问使用索引的姿势有什么问题吗?当索引不能解决慢查询时,一般是业务表数据量大造成的。用空间来交换时间的想法。当读写性能遇到瓶颈时,首先考虑数据库架构是否可以升级。它可以解决问题。如果不是,则需要考虑分库分表分库分表。虽然可以解决读写的瓶颈,但同时也会带来各种各样的问题。需要提前排查解决方案,踩坑线不是你炫耀的地方,稳定才是硬道理。可以用简单的方法解决,不用复杂的方法