不要為了“分庫分表”而“分庫分表”

NO IMAGE

為什麼要進行分庫分表?

當數據庫的數據量過大,大到一定的程度,我們就可以進行分庫分表。那麼基於什麼原則,什麼方法進行拆分,這就是本篇所要講的。

為什麼要進行分庫分表?當數據庫大到一定程度的時候,我們採用優化硬件,優化表的結構,這種方法還是無法滿足的時候,就要進行分庫分表。

分庫分表是什麼?

隨著公司的業務快速發展,數據庫中的數據量猛增,訪問性能也變慢了,優化迫在眉睫。

分析下問題出現哪裡呢?關係型數據本身就比較容易形成系統瓶頸,單機存儲容量,連接數,處理能力都有限。當單表的數據量達到1000W或100G以後,由於查詢維度較多,即使添加從庫,優化索引,做很多操作時性能還是下降嚴重。

方法一:

通過提升服務器硬件能力來提高數據處理能力,比如增加存儲容量,CPU等,這種方案成本很高,並且如果瓶頸在MySQL本身,那麼提高硬件也是很有限的。

不要為了“分庫分表”而“分庫分表”

方法二:

將數據分散在不同的數據庫中,使得單一數據庫的數據量變小來緩解單一數據庫的性能問題,從而達到提升數據庫性能的目的。

比如,將電商的數據庫分為若干個獨立的數據庫,並且對於大表也拆分為若干小表,從而解決數據庫的性能問題。就跟把雞蛋放在多個籃子裡是一樣的。

不要為了“分庫分表”而“分庫分表”

所以,分庫分表就是為了解決由於數據量過大而導致數據庫性能降低的問題,將原來獨立的數據庫拆分為若干數據庫,將數據庫大表拆分成若干數據表,使得單一數據庫,單一數據表的數據量變小,從而達到提升數據庫性能的目的。

分庫分表的方式

我們將電商作為其背景,現在有三個表,分別是賣家表,商品表,店鋪表。

垂直分表

我們平時逛淘寶等電商網站時,搜索列表的頁面顯示商品的關鍵信息,而點進去的頁面顯示商品的詳情信息。這個商品信息大表所包含的字段有很多,所以我們將商品信息中常用的字段歸為一個表,商品信息中不常用的字段歸為一個表。

垂直分表的定義:將一個表按照字段分為多表,每個表裡面都存儲其中一部分字段。

他帶來的提升是:

1.為了避免IO爭搶並減少鎖表的機率,查看詳情的用戶與商品信息瀏覽互不影響。

2.充分發揮熱門數據(商品的基礎信息)的操作效率,商品信息的操作的高效率不會被商品描述的低效率所拖累。

為什麼大字段效率低,比如商品表的描述信息?:第一是由於數據量本身大,需要更長的讀取時間;第二是跨頁,頁是數據庫存儲單位,很多查找及定位操作都是以頁為單位,單頁內的數據行越多數據庫整體性能越好,而大字段佔用空間大,單頁內存儲行數小,因此IO效率低;第三,數據庫以行為單位將數據加載到內存中,這樣表中字段較短且訪問評率交到,內存能加載更多的數據,命中率更高,減少了磁盤IO,從而提升了數據庫性能。

一般來說,當表的數據量很大時,可以將表按字段切開,將熱門字段和冷門字段分開,放在不同的表中,避免發生IO爭搶。

垂直分庫

通過垂直分表性能得到一定程度的提升,但是還沒有達到要求,並且磁盤空間已經不夠了,因為數據庫始終限制在一臺服務器上,庫內的垂直分表只解決了單一表數據量過大的問題,單沒有將表分佈到不同的服務器上,因此每個表還是競爭同一個物理機的CPU,內存,網絡IO,磁盤等物理資源。

所以,我們可以將賣家表,商品表,店鋪表分在不同的服務器中。

垂直分庫是指按照業務將表進行分類,分佈在不同的數據庫中,每個庫可以放在不同的服務器上,他的核心就是專庫專用。

水平分庫

經過垂直分庫,數據庫性能問題得到一定程度的解決,但是隨著業務量的增長,商品單褲存儲數據已經超出預估。粗略估計,目前有8w店鋪,每個店鋪平均150個不同規格的商品,再算上增長,那商品數量得往1500w上預估,而且商品庫屬於訪問非常頻繁的資源,單臺服務器已經無法支撐。此時,該如何優化。

嘗試水平分庫,將店鋪ID為單數和店鋪ID為雙數的商品信息分表放在兩個庫中。

水平分庫是把同一個表的數據按一定規則拆到不同的數據庫中,每個庫可以放在不同的服務器上。

他帶來的提升是:

解決了單庫大數據,高併發的性能瓶頸。

提高了系統的穩定性及可用性。(穩定性體現在IO衝突減少,鎖定減少,可用性指某個庫出問題,部分可用)

水平分表

水平分表是在同一個數據庫內,把同一個表的數據按一定的規則拆到多個表中。(對數據行拆分,不影響表結構)

他帶來的提升

優化單一表數據量過大而產生的性能問題。

避免IO爭搶而減少鎖表的機率。

小結:

本小結介紹了分庫分表的各種方式,他們分別是垂直分表,垂直分庫,水平分庫和水平分表。

垂直分表:可以吧一個寬表的字段按訪問頻次,是否是大字段的原則拆分為多個表,這樣既能使業務清晰,還能提升部分性能,拆分後,儘量從業務角度避免聯查,否則性能方面將得不償失。

垂直分庫:可以把多個表按業務耦合鬆緊歸類,分別存放在不同的庫,這些庫可以分佈在不同服務器,從而使訪問壓力被多服務器負載,大大提升性能,同事能提高整體架構的業務清晰度,不同的業務可根據自身情況定製優化方案,但是他需要解決跨庫帶來的所有複雜問題。

水平分庫:可以把一個表的數據(按數據行)分到多個不同的庫,每個庫只有這個表的部分數據,這些庫可以分佈在不同的服務器上,從而使訪問壓力被多服務器負載,大大提升性能,他不僅需要解決跨庫帶來的所有複雜問題,還要解決數據路由的問題(數據路由問題後邊介紹)。

水平分表:可以把一個表的數據(按數據行)分到同一個數據庫的多張表中,每個表只有這個表的部分數據,這樣做能小幅提升性能,他僅僅作為水平分庫的一個補充優化。

一般來說,在系統設計階段就應該根據業務耦合鬆緊來確定垂直分庫,垂直分表方案,在數據量及訪問壓力不是特別大的情況下,首先考慮緩存,讀寫分離,索引技術等方案,若數據量極大,且持續增長,再考慮水平分庫水平分表方案。

分庫分錶帶來的問題

分庫分表能有效的緩解了單機和單庫帶來的性能瓶頸和壓力,突破網絡IO,硬件資源,連接數的瓶頸,同時也帶來了一些問題。

事務一致性問題

由於分庫分表把數據分佈在不同的庫甚至不同服務器,不可避免的帶來分佈式事務問題。

比如一個請求要先請求數據庫A,再請求數據庫B,這兩個屬於同一個事務,多個庫會導致分佈式事務問題。

跨節點關聯查詢

在沒有分庫前,我們可以很簡單的進行兩表的關聯查詢,但是分庫後,如果兩個表不在同一個數據庫,甚至不在同一臺服務器上,無法進行關聯查詢。

可以將原關聯查詢分為兩次查詢,第一個查詢的結果找出關聯數據id,然後根據id發起第二次請求得到關聯數據,最後將獲得的數據進行拼裝。

跨節點分頁,排序函數

跨節點多庫進行查詢時,limit分頁,order by排序問題,就變得比較複雜,需要先在不同的分片節點中將數據進行排序並返回,然後將不同分片返回的結果集進行彙總和再次排序。

主鍵避重

在分庫分表環境中,由於表中數據同時存在不同數據庫中,主鍵值平時使用的自增長將無用武之地,某個庫生成的ID無法保證全局唯一。因此需要單獨設計全局主鍵,以便面跨庫主鍵重複問題。

公共表

實際應用場景中,參數表,數據字典表等都是數據量較小,變動少,而且屬於高頻聯合查詢的依賴表,但是其又沒有必要分庫分表,比如地理區域表也屬於此類型。

可以將這類表在每個數據庫都保存一份,所有對公共表的更新操作都同時發送到搜的分庫執行。

結語(重點)

如標題所示,我們不能為了分庫分表而分庫分表,首先我們需要知道分庫分表的誕生是因為數據庫的性能瓶頸導致的,也就是如果沒有性能瓶頸,沒必要使用分庫分表,畢竟技術是為了更好的服務於性能。其次,分庫分表也帶來了其他的問題,沒必要時系統變得臃腫,不便。

即,一切以業務為準,不能盲目追求技術的新穎,牛逼。

最後

關注偶哦,領取超多學習資料。

不要為了“分庫分表”而“分庫分表”

相關文章

MyBatisPlusInActionMyBatisPlus實戰

面試官:“談談分庫分表吧?”

全網最全最詳細的ShardingJDBC入門

ShardingJDBC掃盲篇