從一道場景面試題談起

韓楠發表於2022-06-30

面試的經歷,可能大多數DBA都有過。實際上現在的面試題越來越不靠譜,有時候完全按照技術去回答還真的沒法答好。

昨天一個百度的哥們發了條微博,說早上他面了一個阿里的工程師,把他問的面紅耳赤退出了。下午他去阿里面試,面試官正好是上午那個哥們,那哥們把上午他的問題丟擲來讓他回答,他也回答的亂七八糟的。這件事肯定不是真的,不過是在吐槽面試題的奇葩。

正好昨天一個網友說他前幾天去面試,面試官問他一道題目,他回答後面試官就讓他回家等訊息了,然後就沒訊息了。這幾天他一直在為這道題目困擾,想了很久,也諮詢過很多人,找不到問題的關鍵。這道題目的原文如下:


翻譯成中文就是:“想象有一個表儲存所有使用者的餘額資訊。並且大部分select和update查詢都與一條記錄相關(例如公司賬戶餘額/機構使用者頻繁交易),因此這些查詢需要一個接一個地執行。您可以做些什麼來提高這些查詢的效能?”。

這是一個日常比較難以遇到的應用場景,不過面試題一般都會從比較古怪的角度來出。我問他當時的回答,他說當時覺得雖然有點難,但是還是回答出來了。1)利用索引提高每個查詢的效率;2)確保SQL使用了最佳的執行計劃;3)在應用程式上採用批次更新,而不是一個一個的執行。

這是一個從程式設計師的角度來說的不錯的回答,不過如果作為最佳化工程師或者DBA來說,就不夠合格了。實際上這個問題的變種是有個應用頻繁的查詢和更新某些使用者餘額,我們有什麼辦法來進行最佳化。如果問題僅限於此,那麼這個問題就是我們日常十分常見的熱塊問題了。

Hot Block/page或者Buffer Busy Waits這類問題,對於每個DBA來說可能都不難解決,提高BUFFER 命中率、使用hash分割槽等方法打散熱塊、降低資料塊的fillfactor(PG資料庫)或者加大PCTFREE(ORACLE)等都是最佳化的方法。同時提高DB CACHE的命中率,提高IO效能,從總體上降低DB CACHE負擔也是可實施的而最佳化方案。

面試題往往不會出的太簡單,因此這道題上加了點碼,把問題集中到一個更為不常見的場景,那就是所有的查詢操作或者併發寫操作都幾種在其中某一條記錄上。在實際場景種會出現一個比較接近的場景,那就是某銀行的餘額表上突然出現大量的buffer busy waits,等待時間很長,導致了效能問題。

平時的時候,雖然餘額表上的熱塊衝突也比較嚴重,不過還能接受,當某幾個賬號突然出現十分頻繁的高併發操作,就有可能出現這種情況。如果放在一個全面的場景種去考慮這個問題,這個問題還是有解的,解答的方案和前面說的降低熱塊衝突的方案類似。

這種因為修改某種餘額而導致的嚴重效能問題,十多年前我在一個運營商那裡也遇到過,運營商的預付費卡的話費餘額表也有類似的問題,當我們打電話的時候,隨時都要更新這個餘額,當餘額不足的時候,會掐斷這個通話,這是融合計費裡的常見場景。早期的這個業務的實現是透過訪問Oracle資料庫來實現的,因此這個功能經常導致嚴重的效能問題。當時我幫這個運營商做最佳化,採用上述方法後雖然有效果,不過還是無法根治,因此我建議他們把這部分業務放到記憶體資料庫種去,後來他們改造了應用,效果很好。

如果極端到了所有的讀寫操作都幾種在其中某一個賬號上,那麼這個問題似乎又更加複雜了。不過從DBA的角度還是可以想出幾條特殊的最佳化方法。我當時給他的建議是:

1)首先確保索引數量不要太多,冗餘的索引會加大BUFFER BUSY;
2)其次是使用HASH分割槽或者降低fillfactor(POSTGRESQL)或者提高PCTFREE(ORACLE),其他資料庫類似。從而降低某一行的衝突;
3)訪問該記錄的索引如果不經常做範圍掃描,那麼可以建立反轉鍵索引,進一步減少BUFFER BUSY;
4)透過系統級調整,降低LATCH(Oracle)、LWLOCK(Postgresql)、spinlock(Mysql)的爭用,從而減少BUFFER BUSY WAITS的延時;
5)提升IO效能;
6)如果上述方法都無效,那麼最好是把這個業務放入KV的記憶體資料庫,比如Redis中去做處理。


這實際上是一個十分開放的問題,上面也不是標準答案,面試官要的並不是你的正確答案,而是面對這種特殊場景,你的知識能夠組織出來的調整方案。只要你不交白卷,同時掌握了分析這個問題的要點“BUFFER BUSY”,“HOT RECORD”,而且你的方案都是圍繞這個要點的最佳化來進行的,那麼可能面試官給你的分數也不會太低。



來自 “ 白鱔的洞穴 ”, 原文作者:白鱔;原文連結:https://mp.weixin.qq.com/s/5jo01wPbtAsO7KH-Dsu-Tg,如有侵權,請聯絡管理員刪除。

相關文章