1. 程式人生 > >垂直拆分和水平拆分

垂直拆分和水平拆分

概念介紹

垂直拆分

  垂直拆分就是要把表按模組劃分到不同資料庫表中(當然原則還是不破壞第三正規化),這種拆分在大型網站的演變過程中是很常見的。當一個網站還在很小的時候,只有小量的人來開發和維護,各模組和表都在一起,當網站不斷豐富和壯大的時候,也會變成多個子系統來支撐,這時就有按模組和功能把表劃分出來的需求。其實,相對於垂直切分更進一步的是服務化改造,說得簡單就是要把原來強耦合的系統拆分成多個弱耦合的服務,通過服務間的呼叫來滿足業務需求看,因此表拆出來後要通過服務的形式暴露出去,而不是直接呼叫不同模組的表,淘寶在架構不斷演變過程,最重要的一環就是服務化改造,把使用者、交易、店鋪、寶貝這些核心的概念抽取成獨立的服務,也非常有利於進行區域性的優化和治理,保障核心模組的穩定性。如下圖
缺點

垂直拆分單表在大資料量的表中依然存在效能瓶頸


id 列1 列2 列3 列4 列5 列6

以上的表格進行垂直拆分,會變成一下兩個表格(就是個例子,具體還要根據實際情況分析)

id 列1 列2 列3
id 列4 列5 列6

通常會按照一下原則拆分
1. 把不常⽤的欄位單獨放在⼀張表;
2. 把text,blob等⼤欄位拆分出來放在附表中;
3. 經常組合查詢的列放在⼀張表中;

垂直拆分更多時候就應該在資料表設計之初就執⾏的步驟,然後查詢的時候⽤jion關鍵起來即可;
如果系統過於龐大,拆分的表可以放在不同的資料庫中,甚至不同的Server中,怎樣劃分Server就要根據功能模組和專案實際劃分。而有些頻繁使用的資料也一定要做讀寫分離;

比如微博和阿里。讀和寫都比較頻繁,肯定會做讀寫分離。
如果日誌資訊也放在了資料庫中的一張表中,每天近千萬條的日誌,那麼一天表中的資料量就會很大,在做查詢或者其他更新資料時,就會很緩慢,那這時就要考慮水平拆分了。

水平拆分

  上面談到垂直切分只是把表按模組劃分到不同資料庫,甚至資料庫也分為了不同Server,但沒有解決單表大資料量的問題

,而水平切分就是要把一個表按照某種規則把資料劃分到不同表或資料庫裡。例如像計費系統和日誌系統。通過按時間來劃分表就比較合適,因為系統都是處理某一時間段的資料。而像SaaS應用,通過按使用者維度來劃分資料比較合適,因為使用者與使用者之間的隔離的,一般不存在處理多個使用者資料的情況,簡單的按user_id範圍來水平切分

通俗理解:水平拆分行,行資料拆分到不同表中; 垂直拆分列,表資料拆分到不同表中

id 列1 列2 列3

一段時間或者滿足最初定義的規則後,進行水平拆分,也就進行資料的行拆分,表的結構不發生變化

id 列1 列2 列3

拆分原則
通常情況下,我們使⽤取模的⽅式來進⾏表的拆分;⽐如⼀張有400W的⽤戶表users,為提高其查詢效率我們把其分成4張表users1,users2,users3,users4 ,通過用id取模的方法把資料分散到四張表內Id%4+1 = [1,2,3,4]然後查詢,更新,刪除。
例如:id = 17,17%4 + 1 = 2, $tableName = ‘users’.’2’
Select * from users2 where id = 17;
在insert時還需要⼀張臨時表uid_temp來提供自增的id,該表的唯⼀⽤處就是提供⾃增的ID;

insert into uid_temp values(null);

得到⾃增的ID後,又通過取模法進行分表插⼊;
注意:進行水平拆分後的表,欄位的列和型別和原表保持一致,但是要記得去掉auto_increment自增長。

另外部分業務邏輯也可以通過地區,年份等欄位來進行歸檔拆分

進⾏拆分後的表,只能滿足部分查詢的高效查詢需求,這時我們就要在產品策劃上,從界⾯上約束使用者查詢⾏為
比如我們是按年來進行歸檔拆分的,這個時候在頁⾯設計上就約束⽤戶必須要先選擇年,然後才能進行查詢;
在做分析或者統計時,由於是自己公司內部工作的需求,多點等待其實是沒關係的,並且併發很低,這個時候可以⽤union把所有表都組合成⼀張檢視來進⾏查詢,然後再進⾏查詢;

使用場景

垂直與水平聯合切分

  由上面可知垂直切分能更清晰化模組劃分,區分治理,水平切分能解決大資料量效能瓶頸問題,因此常常就會把兩者結合使用,這在大型網站裡是種常見的策略

案例:
以mysql為例,簡單購物系統暫設涉及如下表:
1. 產品表(資料量10w,穩定)  
2. 訂單表(資料量200w,且有增長趨勢)  
3. 使用者表 (資料量100w,且有增長趨勢) 
垂直拆分:
  解決問題: 表與表之間的io競爭
  不解決問題: 單表中資料量增長出現的壓力
  方案:

  1. 把產品表和使用者表放到一個server上
  2. 訂單表單獨放到一個server上

水平拆分:
  解決問題: 單表中資料量增長出現的壓力
  不解決問題: 表與表之間的io爭奪
  方案:

  1. 使用者表通過性別拆分為男使用者表和女使用者表;   
  2. 訂單表通過已完成和完成中拆分為已完成訂單和未完成訂單;  
  3. 產品表未完成訂單放一個server上;   
  4. 已完成訂單表盒男使用者表放一個server上;   
  5. 根據新使用者和老使用者,因為新使用者相應的活躍度高;