如何準備數據庫方面的面試問題
- 2022 年 1 月 19 日
- 筆記
作為面試官,我會按如下層次考核求職者數據庫方面的技能。
1 問基本的操作技能,這裡當然不會直接問sql語法,而會挑些點來問,比如左連接怎麼做,with語句或merge語句的含義和用法。
2 問些高級技能,其中包括事務等,比如問事務隔離級別和傳播機制。也包括索引,比如索引的底層,索引的數據結構和索引的種類。
以上都是比較基礎的,如果是初級開發的話,能說好上面的問題就好了,如果是要面試3年及以上的高級開發,還會問如下的調優技能和分佈式組件技能。
3 調優技能一般會問,在你們的項目里,一般是怎麼發現慢sql,發現慢sql以後會用什麼方式來排查和解決?或者問,你們設計數據庫表和數據庫索引的時候,一般是怎麼考慮的?或者就問個開放性的問題,你們是怎麼排查和解決數據庫性能問題的?
4 數據庫方面的組件一般包括redis緩存組件和mycat分庫組件,一般會問,你們項目里有沒有用過?結合一個例子告訴我怎麼用?如果是面高級或資深開發時,還會深入問些,比如用到的redis是集群還是單機版?怎麼做redis持久化?redis的緩存穿透問題有沒有遇到過?Mycat怎麼實現分庫的?mycat組件上線後是怎麼做數據遷移的?
在對應準備數據庫方面的面試時,題好背,如果不知道怎麼背題,多看看網文多參加幾次面試就行,但數據庫調優方面的問題,是無法迴避的,比如面試官就一句,你們項目是怎麼分析和排查數據庫性能問題的?
在系統寫調優方面的回答模版前,先說下如下回答的價值,如果初級開發(工作經驗少於3年)能說好,能超越大多數的競爭者,而哪怕高級開發說好這些話,也能讓面試官感覺你很資深,而對於架構師而言,這些回答是基本的標配項。下面具體說下數據庫調優方面該怎麼說?
1 總是先要發現待調優的sql語句,這塊可以通過new relic,或zabbix或cat組件來發現,比如通過配置把這些組件連接到對應的數據庫服務器上,如果出現超過閾值的慢sql,或發郵件告警。如果再不濟,可以直接說,把mysql數據庫配置到linux服務器上,運維人員做來配置,所以一旦出現運行時間超過10秒(或其他配置值)的sql語句,我會收到告警郵件。
這塊一定要說,否則連哪些sql要優化也不知道,怎麼做優化?事實上如果這塊好好準備,還能說好系統監控組件這一塊。
2 發現慢sql以後,首先用執行計劃(sql explain)去分析下該sql語句耗時主要耗在哪塊?一般耗時長的點會有,沒建索引或沒走索引,大表關聯導致耗時長,或長sql語句里,同一個sql塊被之行多次。當然還有其他可能會費時間的點,但上述點經常會遇到,也好準備。
通過執行計劃分析到慢sql的原因後,就可以針對性地說解決方案。可以是建索引,但這裡要注意,被建索引的表規模至少十萬級,而被建索引的字段應當重複率低,否則索引建了白建,這些原因自己查,但我在面試求職者時,真聽說過為幾千條表規模建索引,以及為性別字段建索引的說辭。
調優要點還可以是在建表層面,比如預估一個業務點(比如商品業務)數據表規模很大,到至少十萬級,那麼就別再按三範式建表,因為三範式雖然不會有冗餘數據,但表關聯起來吃不消,遇到這種情況,可以把商品的所有字段放到一個大表,也就是用反範式來建表。但如果求職者是表設計好以後入項目組的,就別說這種話了。
調優要點還包括,用with語句把長sql里運行多次的sql塊提出來,或者乾脆重寫sql。當然還有些說辭,比如更改mysql里關於鎖的配置,或者跳低oracle的水平位,但這種話別說,因為做項目時不大可能全局性地修改mysql或oracle的配置,這樣風險太大。
3 以上是單機版的調優手段,說好這塊還可以說redis緩存調優,這塊該怎麼說呢?先準備個業務點,比如發訂單,在這過程中會多次訪問用戶表,此時第一次訪問時,就可以把數據放入緩存,然後準備下放入緩存用戶數據的結構(無非是list或hash型),然後準備下java訪問redis的api,應該是用Jedis或RedisTemplate。
在此基礎上,可以說下解決過redis的緩存穿透問題,無非是緩存空數據或不存在的數據,同時可以說下,為了避免緩存的數據一直存在於內存,所以需要設置緩存數據的超時時間。
如果是初級開發,說到這個程度就可以了,而且還可以說是用到單機版的redis,如果是高級開發,還可以說下用了redis集群,但用的時候基本上是主從集群,向主節點寫,主節點向從節點同步數據,從從節點讀緩存。但別說用哨兵集群,因為現在不怎麼用了,如果要說用cluster集群也行,但cluster集群單點失效方面的問題很難回答,這要自擔風險,其實如果感覺不怎忙好準備,說個主從redis集群也行。
4 如果再想往深了說,可以說引入了mycat分庫分表組件。這塊基本的該怎麼說呢?有張千萬級別(至少百萬級別)的大表,比如訂單流水表,通過配置mycat參數,按id取模的方式,把它們分散到5個表結構一樣的字表裡,比如id%5是1分到1號子表,依次類推。
用了mycat前,需要排查針對該表的所有sql語句,即所有sql語句都要包含分庫字段,比如id,而且不能有針對全表的操作,比如group by等,如果遇到全表操作,需要改寫,或用java業務實現。
說到這種程度,就能從發現到排查的流程角度,全面地展示自己數據庫調優方面的技能。而且不僅能展示單機版的調優技能,還能展示分佈式組件級別的調優技能。這套話說下來,哪怕去面需要5年工作經驗的高級開發,至少在數據庫層面能及格,更何況去面只要3年以內的初級開發崗。
如果大家想進一步了解我的情況,可以關注我。