Java技术面试主要是围绕Java核心、数据库、Spring Boot框架和分布式组件这四个方面来提问,前文也讲述了快速提升这四方面技能的技巧。在此基础上,本文将在数据库层面,给出准备面试说辞的方法。

1 全面准备不偏科,围绕项目说亮点

    在相关面试说辞前,先给出准备说辞的技巧。

  1. 全面准备事务、索引、调优和缓存分布式组件,别偏重一方面。如果你仅仅把其中一点说得天花乱坠,但其它点没说好,面试官一定会认为你数据库方面能力很差,想靠背题来蒙混过关。
  2. 大多开发一般在面试前不准备,所以面试时只能展示增删改查技能,所以你一定得准备调优和分布式组件相关说辞。
  3. 药无需贵,对症即可,所以不需要准备其它诸如“MySQL底层”等说辞,就结合项目把本文给出的说辞说好即可,这样你的数据库技能就具备了“项目开发经验”。  

2 数据库方面必问的点

    如下问题属于必考点,大家别抱有幻想,一定得准备。

  1.     说下JDBC有哪些组件?如何用JDBC对象访问数据库?   
  2.     事务是什么?事务隔离级别和事务传播机制是什么?
  3.     用JPA(或Mybatis)操作数据库会用到哪些对象和注解?
  4.     三范式是什么?你建表时会用到什么原则?
  5.     左连接、外连接和内连接是什么?

    上述问题大家能从网上找到答案,所以这里就不展开了,不过除了上述基本问题外,数据库方面你在面试时大概率还会被问到如下的问题。

  1.     索引底层数据结构?复合索引和最左匹配原则?如何通过索引优化sql语句?
  2.     项目里你用过哪些数据库的调优手段?你排查过哪些数据库问题?
  3.     项目里你用过哪些缓存?    

    这些问题涉及到性能调优和缓存分布式组件,不过根据我面试的情况,很多候选人基本都不会准备这些问题。而后文就将告诉你详细的准备方式。

3 你有没有用过索引?

    这个问题不问便罢,如果遇到,你可以按层次说出如下的说辞。

    在项目里,我有用索引优化数据库性能的经验,同时也看过索引的底层结构。(先说明在项目里用过)

    索引的底层结构是个B+树,大致结构如下图所示,所以它能用较快的性能找到数据。(找张纸画出下图,边画边说,你自己可以想象这番说辞的分量)

    

 

    然后话锋一转再说,索引是需要消耗硬盘空间的,而且遇到大批量数据读写时,重建索引需要消耗代价,所以我们项目组用索引会非常谨慎。

    (面试官可能就会感兴趣地再问,那你们是在哪些情况下用索引?这正中你下怀)

    只有当数据表规模很大,超过百万,并且这个需要频繁读该字段,且这个字段空值和重复值不多时,才会对该字段建索引。(这种情况才能最大发挥索引的价值)比如在订单模块里的订单流水表的“订单ID”,符合上述情况,所以会建索引。(以项目举例说明,证明你真的用过)

    (说到这里别停,继续往下说)建好索引以后,我在写SQL会非常注意,比如orderID='xxx'和orderID like 'abc%'时,才会确保该条sql走索引,像orderID!='xxx'或遇到左值操作比如substr(orderID,3)='xxx'时,不会走索引,所以这种写法我会避免。     

    说到这里,面试官一般就会认为你具备基本的调优技能了,可能有些面试官还会再深入问,你知不知道“复合索引”?

    我知道,建复合索引需要考虑最左匹配原则,则(a,b,c)这种复合索引,遇到a=xx and b=xx,会走索引,但遇到b=xx的情况就不会走,同时建复合索引是为了避免因“回表”而导致的性能损耗。

    这样一来面试官对你的好感又会再增一步。

4 你知不知道事务?

    我在项目里用过事务。从理论上讲,事务具有要么全做要么全不做的(acid)特性。

    (赶紧落实到项目)在项目里,我们会在Spring的@Service类里通过@Transactional注解来使用事务。(一般都这样用的)

    同时会非常注意其中的事务隔离级别和事务传播机制参数。(哪怕面试官真深入问,你由于准备过也不怕)

    (进一步涉及性能调优)在设置隔离级别时,我们不会调太高,比如绝不会用“读未提交”,因为这样的话,多条SQL来的时候会锁表,会导致其它SQL处于等待状态,但不释放连接,从而会导致连接打满,造成数据库崩溃。(当你说出这番话时,面试官就会认为你有解决实际问题的经验)。   

5 项目里你用过哪些调优手段?

    你别仅局限于此,你可以先说,我们项目里,(mysql)数据库是部署在linux上,其中一旦遇到执行时间超过10秒的sql,我们会收到邮件并分析问题。

    这样一来你更回答了“如何监控以及哪些SQL需要调优”的问题,然后继续往下说。

    遇到慢SQL后,我会用explain观察执行计划,看时间耗费在哪里,大多数情况下是走了全表扫描,这就需要建索引,有时候两个大表关联也会导致慢sql,这就需要缓存或重构表结构。在个别复杂的sql里,会发现多个子查询执行了多次,这就需要用with语句重构sql。(一般来说,索引,缓存,with重构和重构表能解决大多数问题) 

    然后你再多说一句,在我们项目里,一方面会尽可能优化单句SQL语句,另一方面还用到了Redis缓存来优化性能,这样就自然地把话题转到更值钱的分布式组件上了。 

6 你有没有用过缓存?

    我们项目是用Redis作为缓存,(把Redis融入项目,这样就能证明具有项目经验,不过前提是,你需要把Redis五种基本数据类型和读写方式看熟悉) ,再具体讲,是用Jedis库的lpush和lrange方法来读写Redis的列表对象(用具体的方法进一步证明你用过)。

    话锋一转讲需求,证明有使用的必要。比如有个场景,订单模块会经常向风控模块查询公司的风控信息,所以我们把订单ID加前缀作为键,把风控信息存放列表里返回。

    单纯会用Redis的人不少,所以你还要进一步结合项目背景说明更高级的技能。

  1.  在用Redis缓存风控数据时,需要用expire方法设置超时时间为1天左右,否则缓存的数据会一直存在内存里,导致OOM问题。
  2.  在设缓存时,会加一个随机时间,比如1天+(60秒内)随机数,这样同一批数据不会同时失效,造成某个时间段里请求全涌向数据库,导致数据库压力过大。
  3.  在缓存数据时,更要缓存空值和(出现3次以上的)不存在的风控ID值,这样能避免这些请求穿透缓存涌向数据库,造成数据库压力过大。
  4.  项目里是采用了MySQL主从+Redis主从的架构,这样能避免因单点MySQL或Redis失效而导致的问题。
  5.  本项目的Redis采用AOF的方式持久化数据(事先了解下AOF和RDB持久化的说辞)。

    上述缓存说辞再外带你之前展示的数据库索引,性能调优和事务等方面说辞,甚至能让面试官认为你具备5年所有的开发经验,因为很多高级开发在数据库方面的面试表现,不过如此。     

7 大多数初级开发在数据库方面的表现

    我最近面试过多位具有3年开发经验的候选人,他们在数据库方面的表现真的很一般。其实大家也可以思考下,如果你不准备,能否比他们回答得更好?

    “在Spring Boot里,你怎么连接数据库?”,大多数候选人都能结合JPA注解很好说明。

    “你有没有用过索引?”大多数候选人能说出通过索引能优化性能,我继续问,“哪些场景下需要建索引?哪些SQL建了索引也无法用到?复合索引用过没?”这些问题不少人就说不上了。

    事务概念大多知道,但我问“你们项目里,用的事务隔离级别是哪个?为什么?”能答出来的人就比较少了。 

    Redis方面,大多数人能讲述基本数据结构以及Jedis的相关语法,但“缓存空值防穿透”以及“设置超时时间防OOM”等资深技能,就很少有人能说好了。

    两厢一比,如果你第一按本文给出的提示通过查资料熟悉范式等概念,第二再结合项目很好地围绕索引、事务、执行计划性能调优和Redis缓存展示技能,那么至少在数据库这方面,你就能比很多人强。

    当然除了数据库以外,面试更会考Java核心和分布式组件等技能,在本系列的其它文章里,还会给出准备其它方面面试说辞的技巧,敬请关注。 

 

 

posted on 2022-12-12 13:01  hsm_computer  阅读(260)  评论(0编辑  收藏  举报