目前很多互聯網系統都存在單表數據量過大的問題,這就降低了查詢速度,影響了客戶體驗。為了提高查詢速度,我們可以優化sql語句,優化表結構和索引,不過對那些百萬級千萬級的數據庫表,即便是優化過后,查詢速度還是滿足不了要求。這時候我們就可以通過分表降低單次查詢數據量,從而提高查詢速度,一般分表的方式有兩種:水平拆分和垂直拆分,兩者各有利弊,適用於不同的情況。
水平拆分
水平拆分是指數據表行的拆分,表的行數超過200萬行時,就會變慢,這時可以把一張的表的數據拆成多張表來存放。
通常情況下,我們使用取模的方式來進行表的拆分;比如一張有400W的用戶表users,為提高其查詢效率我們把其分成4張表users1,users2,users3,users4
通過用ID取模的方法把數據分散到四張表內Id%4+1 = [1,2,3,4]
然后查詢,更新,刪除也是通過取模的方法來查詢。
例:QQ的登錄表。假設QQ的用戶有100億,如果只有一張表,每個用戶登錄的時候數據庫都要從這100億中查找,會很慢很慢。如果將這一張表分成100份,每張表有1億條,就小了很多,比如qq0,qq1,qq1…qq99表。
用戶登錄的時候,可以將用戶的id%100,那么會得到0-99的數,查詢表的時候,將表名qq跟取模的數連接起來,就構建了表名。比如123456789用戶,取模的89,那么就到qq89表查詢,查詢的時間將會大大縮短。
另外部分業務邏輯也可以通過地區,年份等字段來進行歸檔拆分;進行拆分后的表,只能滿足部分查詢的高效查詢需求,這時我們就要在產品策划上,從界面上約束用戶查詢行為。比如我們是按年來進行歸檔拆分的,這個時候在頁面設計上就約束用戶必須要先選擇年,然后才能進行查詢;在做分析或者統計時,由於是自己人的需求,多點等待其實是沒關系的,並且並發很低,這個時候可以用union把所有表都組合成一張視圖來進行查詢,然后再進行查詢。
垂直拆分
垂直拆分是指數據表列的拆分,把一張列比較多的表拆分為多張表。把大的字段拆分到另一個表,並且該表與原表是一對一的關系。
垂直拆分的優點是:
1. 可以使得數據變小,一個數據塊(block)就能存放更多的數據,在查詢時就會減少I/O次數(每次查詢時讀取的Block就少,磁盤按頁儲存,在B+樹葉節點一頁可以放更多行數據。數據小,讀一個范圍的數據可能只用讀一頁一次IO就夠了)
2. 可以達到最大化利用Cache的目的,具體在垂直拆分的時候可以將不常變的字段放一起,將經常改變的放一起(更新操作會讓查詢緩存無效)
3. 數據維護簡單
(垂直分表的意義:https://juejin.im/post/5b652a385188251b176a873e)
通常我們按以下原則進行垂直拆分:
1,把不常用的字段單獨放在一張表;,
2,把text,blob等大字段拆分出來放在附表中;
3,經常組合查詢的列放在一張表中;
例如學生答題表tt:有如下字段:
Id name 分數 題目 回答
其中題目和回答是比較大的字段,id name 分數比較小。
如果我們只想查詢id為8的學生的分數:select 分數 from tt where id = 8;雖然知識查詢分數,但是題目和回答這兩個大字段也是要被掃描的,很消耗性能。但是我們只關心分數,並不想查詢題目和回答。這就可以使用垂直分割。我們可以把題目單獨放到一張表中,通過id與tt表建立一對一的關系,同樣將回答單獨放到一張表中。這樣我們插敘tt中的分數的時候就不會掃描題目和回答了。