面試官:說說Mysql資料庫分庫分表,並且會有哪些問題

2020-12-17 yes的練級攻略

之前一篇文章面試官:說說Mysql讀寫分離,並且有哪些注意事項?已經談到了資料庫集群之主從集群也就是讀寫分離,也提到了讀寫分離其實只是分擔了訪問的壓力,但是存儲的壓力沒有解決。

存儲的壓力說白了就是隨著系統的演化,需求的增加,可能表的數量會逐漸增多,比如一段時間上個新功能就得加個表。並且隨著用戶量的增多類似用戶表的行數肯定會增多,訂單表的數據肯定會隨著時間而增多,當這種數據量達到千萬甚至上億的時候,讀寫分離就已經滿足不了,讀寫性能下降嚴重。

也就是一臺伺服器的資源例如CPU、內存、IO、磁碟等是有限的,所以這時候分庫分表就上啦!

分庫

分庫講白了就是比如現在你有一個資料庫伺服器,資料庫中有兩張表分別是用戶表和訂單表。如果要分庫的話現在你需要買兩臺機子,搞兩個資料庫分別放在兩臺機子上,並且一個資料庫放用戶表,一個資料庫放訂單表

這樣存儲壓力就分擔到兩個伺服器上了,但是會帶來新的問題,所以東西變複雜了都會有新的問題產生。

1、聯表查詢問題

也就是join了,之前在一個資料庫裡面可以用上join用一條sql語句就可以聯表查詢得到想要的結果,但是現在分為多個資料庫了,所以join用不上了。就比如現在要查註冊時間在2019年之後用戶的訂單信息,你就需要先去資料庫A中用戶表查詢註冊在2019年之後的信息,然後得到用戶id,再拿這些id去資料庫B訂單表中查找訂單信息,然後再拼接這些信息返回。所以等於得多寫一些代碼了。

2、事務問題

搞資料庫基本上都離不開事務,但是現在不同的資料庫事務就不是以前那個簡單的本地事務了,而是分布式事務了,而引入分布式事務也提高了系統的複雜性,並且有些效率不高還會影響性能例如Mysql XA。還有基於消息中間件實現分布式事務的等等這裡不展開講述。

分表

我們已經做了分庫了,但是現在情況是我們的表裡面的數據太多了,就一不小心你的公司的產品火了,像抖音這種,所有用戶如果就存在一張表裡吃不消,所以這時候得分表。分別又分垂直分表和水平分表。

1、垂直分表

垂直分表的意思形象點就像坐標軸的y軸,把x軸切成了兩半,對應到我們的表就是比如我們表有10列,現在一刀切下去,分成了兩張表,其中一張表3列,另一張表7列。

這個一刀切下去讓兩個表分別有幾列不是固定的,垂直分表適合表中存在不常用並且佔用了大量空間的表拆分出去。

就拿頭條的用戶信息,比如用戶表只有用戶id、暱稱、手機號、個人簡介這4個欄位。但是手機號和個人簡介這種信息就屬於不太常用的,佔用的空間也不小,個人簡介有些人寫了一坨。所以就把手機號和個人簡介這兩列拆分出去。

那垂直分表影響就是之前只要一個查詢的,現在需要兩次查詢才能拿到分表之前的完整用戶表信息。

2、水平分表

水平分表的意思形象點就像坐標軸的x軸,把y軸切成了兩半(當然不僅限於切一刀,可以切好幾份)。也拿用戶表來說比如現在用戶表有5000萬行數據,我們切5刀,分成5個表,每個表1000萬行數據。

水平分表就適合用戶表行數很多的情況下,一般單表行數超過5000萬就得分表,如果單表的數據比較複雜那可能2000萬甚至1000萬就得分了,這個得看實際情況有些表很簡單可能一億行都不用分。所以當一個表行數超過千萬級別的時候關注一下,如果沒有性能問題就可以再等等看,不要急著分表,因為分表會是帶來很多問題。

水平分表的問題比垂直分表就更煩了。

要考慮怎麼切,講的高級點就叫路由

1、按id也就是範圍路由

比如id 值1-999萬的放一張表,1000萬-1999萬放一張表,一次類推。這個得試的,因為範圍分的大了,可能性能還有問題,範圍分的小了。。那表不得多死。

這種分法的好處就是容易切啊,簡單粗暴,以後新增的數據分表都不會影響到之前的數據,之前的數據都不需要移動。

2、哈希路由

就是取幾列哈希一下看看數據哪個庫,比如拿id來做哈希,1500取餘8等於4,所以這條記錄就放在user_4這個表中,2011取餘8等於3,所以這條記錄就放在user_3中。這種分法好處就是分的很均勻,基本上每個表的數據都差不多,但是以後新增數據又得分表了咋辦,以前的數據都得動,比較煩!

3、搞一張表來存儲路由關係

還是拿用戶表來說,就是弄一個路由表,裡面存userId和表編號,表示這個userId是這張user表的的。這種方式也簡單,之後又要分表了之後改改路由表,遷移一部分數據。但是這種方法導致每次查詢都得查兩次,並且如果路由表太大了,那路由表又成為瓶頸了!

再說說查詢時候的問題。

比如你要查註冊時間最早的前100名用戶,這就等於你得在水平分的每一張表都order by 一下註冊時間並且取100個,然後再把每個表的100個結果對比一下得到最終的結果。首先操作變麻煩了,以前一個order by就搞定的事情現在變的複雜了,而且還得考慮一個因素就是時間的問題,如果你拆成了20個表,那你得執行20個order by,如果是串行執行的話,這個時間開銷也是個問題!

分庫分表的實現

具體實現也分為程序代碼封裝、資料庫中間件封裝。實現難度會比讀寫分離更大,至於兩種封裝的比較在講讀寫分離時候已經說了,這裡不再贅述。

總結

說了這麼多好像分庫分表一點都不好啊,沒錯會引入很多問題,所以在架構設計要遵循演化原則,任何東西都不是一蹴而就的,在不同場景適配不同的架構,架構只有合適的,沒有一個架構可以適配任何場景。

在軟體中簡單夠用就是好的,技術沒有貴賤,不是用了分布式就牛逼,越複雜的系統維護的成本和難度越高,出現問題的機率越大。這種架構的演化往往都是被用戶所驅動的,可以說是"不得已而為之"。

基本上單機資料庫可以支撐10萬用戶量級別。所以一般情況下像資料庫吃不消就升級硬體,優化資料庫配置、優化代碼、引入redis等。只有在真的不行了才上這些更複雜的東西。

如有錯誤歡迎指正!

相關焦點

  • MySQL:網際網路公司常用分庫分表方案匯總
    作者:尜尜人物cnblogs.com/littlecharacter/p/9342129.html本文目錄一、資料庫瓶頸二、分庫分表三、分庫分表工具四、分庫分表步驟五、分庫分表問題非partition key的查詢問題非partition key跨庫跨表分頁查詢問題
  • 分庫分表的4個面試連環炮問題!不會就慘了
    面試中我們經常會碰到的關於分庫分表的幾個面試連環炮!今天就給大家一一介紹!希望對大家面試的時候能夠有所幫助!一、面試題為什麼要分庫分表(設計高並發系統的時候,資料庫層面該如何設計)?用過哪些分庫分表中間件?不同的分庫分表中間件都有什麼優點和缺點?你們具體是如何對資料庫如何進行垂直拆分或水平拆分的?
  • 必知必會! MySql 高頻企業面試題
    1、首先導出庫的表結構 -d 只導出表結構,然後批量替換3、然後全局替換set names = xxxxx4、刪除原有庫與表,並新創建出來,再導入建庫與建表語句與所有數據40:MYSQL資料庫伺服器性能分析的方法命令有哪些?
  • 分庫分表就能無限擴容嗎,解釋得太好了!
    Dubbo 就是為了解決這個問題而生的。3. 分庫分表如果你的公司產品很受歡迎,業務繼續高速發展,數據越來越多,SQL 操作越來越慢,那麼資料庫就會成為瓶頸,那麼你肯定會想到分庫分表,不論通過 ID hash 或者 range 的方式都可以。
  • 分庫分表常見概念解讀+Sharding-JDBC實戰
    為了讓新手也能看得懂,有些知識點我可能會用更多的篇幅加以描述,希望大家不要嫌我囉嗦,等這分庫分表系列文章完結後,我會把它做成 PDF 文檔開源出去,能幫一個算一個吧!如果發現文中有哪些錯誤或不嚴謹之處,歡迎大家交流指正。具體實踐分庫分表之前在囉嗦幾句,回頭複習下分庫分表的基礎概念。
  • mysql┃多個角度說明sql優化,讓你吊打面試官!
    3.4可以使用force index()防止優化器選錯索引 3.5事務語句順序 4.分庫分表● 結語 前言 mysql的優化是我們經常都會提到的一個話題,也是重中之重,在很多大廠中會有專門的DBA來做這件事情,甚至更過分的是連應屆生的招聘崗位要求上都寫了需要懂一點
  • 面試官:談談你對MySQL事務的認識?
    引言今天回頭繼續講講資料庫系列的文章。這篇文章屬於mysql資料庫系列,我們來談談事務方面的常見面試題。那麼,具體題目有下面這些:1、講講為什麼用事務?事務的四大特性?事務的隔離級別知道吧,你們生產用哪種?2、Innodb中ACID具體是如何實現的?3、redo log和binlog的一致性如何保證?4、大事務有哪些壞處?生產上遇到過大事務麼?
  • 分庫分表:TiDB,求別搶飯碗!
    但是引入了中間件肯定就會增加各方面的維護成本,這篇帶大家了解一款替代分庫分表的解決方案:分布式資料庫:TiDB 前言 如今硬體的性價比越來越高,網絡傳輸速度越來越快,資料庫分層的趨勢逐漸顯現,人們已經不再強求用一個解決方案來解決所有的存儲問題,而是通過分層,讓緩存與資料庫負責各自擅長的業務場景。
  • 數據量大了一定要分表,分庫分表Sharding-JDBC入門與項目實戰
    最近項目中不少表的數據量越來越大,並且導致了一些資料庫的性能問題。因此想藉助一些分庫分表的中間件,實現自動化分庫分表實現。調研下來,發現Sharding-JDBC目前成熟度最高並且應用最廣的Java分庫分表的客戶端組件。
  • 資料庫面試題:MySQL大數據量下的優化-乾貨整理
    資料庫面試題 這個題可說的點實在太多了, 試官很有可能跟據下 說的優化進 來問問題。參考前 的查詢在什麼情況下不 索引 加緩存NoSQL Memcached Redis 分區 MySQL內置的是 平分區,分為range,list,hash,key 在分區的基礎上還可以有
  • 一文快速入門分庫分表中間件 Sharding-JDBC(必修課)
    ,我們在前文中回顧了一下分庫分表的基礎知識,對分庫分表的拆分方式有了一定的了解。核心概念在開始 Sharding-JDBC分庫分表具體實戰之前,我們有必要先了解分庫分表的一些核心概念。2.1 分片一般我們在提到分庫分表的時候,大多是以水平切分模式(水平分庫、分表)為基礎來說的,數據分片將原本一張數據量較大的表 t_order 拆分生成數個表結構完全一致的小數據量表 t_order_0、t_order_1、···、t_order_n,每張表只存儲原大表中的一部分數據,當執行一條SQL時會通過
  • 分庫分表【Sharding-JDBC】入門與項目實戰
    小Hub領讀:Sharding-JDBC,這麼主流的分庫分表框架,你還不懂?來了解一下,然後入門吧!
  • MySQL面試必會100道題
    10.查看創建的用戶oldboy擁有哪些權限11.查看當前資料庫裡有哪些用戶12.進入oldboy資料庫13.創建一innodb GBK表test,欄位id int(4)和namevarchar(16)14.查看建表結構及表結構的
  • 簡單粗暴的分庫分表設計方案
    來源於:https://zhuanlan.zhihu.com/p/374386521.數據散列模式數據散列模式主要是通過hash算法將數據隨機寫入(分庫)分表中,用以提高資料庫的負載能力,這種設計方案下分表欄位通常需要被包含在分表中。優點:可以解決有局部熱點的數據的負載均衡,並整體提高資料庫的負載能力。
  • Sharding-jdbc的實戰入門之水平分表(一)
    經常碰到一些小夥伴的問題,就是我們到達什麼量級才會分庫分表?分庫分表經驗值mysql單表經驗一般MySQL單表1000W左右的數據是可以不需要考慮分表的。但是要避免過度設計(考慮了很多未來幾年的需求,例如一張表在未來幾年內數據預計會達到幾千萬,這個就過渡考慮了)根據數據量增長速度,選擇實現步驟第一步:不分庫不分表第二步:同庫內的分表第三步:分庫分表不要過度設計,一上來玩大的就進行分庫分表分庫如果
  • 面試官邪魅一笑:MySQL千萬級別大表,你要如何優化?
    ,字符串為主的表在五百萬以下是沒有太大問題的。這裡重點介紹下服務層的緩存實現,目前主要有兩種方式:直寫式(Write Through):在數據寫入資料庫後,同時更新緩存,維持資料庫與緩存的一致性。這也是當前大多數應用緩存框架如Spring Cache的工作方式。這種實現非常簡單,同步好,但效率一般。回寫式(Write Back):當有數據要寫入資料庫時,只會更新緩存,然後異步批量的將緩存數據同步到資料庫上。
  • 京東面試:說說MySQL的架構體系
    字數:3620,閱讀耗時:4分35秒最近群裡一位兄弟在面試中被問到:「MySQL的架構體系是什麼」。雖然他搞java開發好幾年了,也一直使用的是MySQL資料庫,但是面對這個問題依然是一臉懵逼,還以為面試官要問索引、慢查詢、性能優化之類的(因為這些都是網上找點面試題背過了)。
  • MYSQL面試常考知識點總結
    ,這就是所謂的分表!分庫     分表能夠解決單表數據量過大帶來的查詢效率下降的問題,但是,卻無法給資料庫的並發處理能力帶來質的提升。面對高並發的讀寫訪問,對資料庫進行拆分,從而提高資料庫寫入能力,這就是所謂的分庫!
  • 分庫分表?如何做到永不遷移數據和避免熱點?
    上圖中訂單數據達到了4000萬,我們也知道mysql單表存儲量推薦是百萬級,如果不進行處理,mysql單表數據太大,會導致性能變慢。使用方案可以參考數據進行水平拆分。把4000萬數據拆分4張表或者更多。當然也可以分庫,再分表;把壓力從資料庫層級分開。
  • 一個億級分庫分表項目的實戰全過程解析
    分庫分表的文章網上非常多,但是大多內容比較零散,以講解知識點為主,沒有完整地說明一個大表的切分、新架構設計、上線的完整過程。因此,我結合去年做的一個大型分庫分表項目,來復盤一下完整的分庫分表從架構設計到發布上線的實戰總結。為什麼需要做分庫分表?這個相信大家多少都有所了解。