前言
現代業務越來越複雜,資料量也越來越大,關係型資料庫本身就比較容易形成系統瓶頸,單機儲存容量,連線數,處理能力都有限。
當單表的資料量達到一定量級以後,比如1000萬,由於查詢維度較多,即使新增從庫,優化索引,做很多操作時效能還是下降嚴重。
這個時候要如何提高資料的效能呢?
有人說,可以通過提升伺服器硬體能力來提高資料處理能力,比如換更快的硬碟,換更強的CPU。
這種方案成本是很高的,並且瓶頸有時候往往不在硬體上,而在資料庫本身。
基於這種現狀,分表/分庫就出現了!
什麼是分別分庫
分表分庫是兩種操作,一種是分表,一種是分庫。
但是他們的中心思想都是將資料分散,使得單一資料庫/表的資料量變小來緩解單一資料庫的效能問題,從而達到提升資料庫效能的目的。
例如,將某業務的資料庫分為若干個獨立的資料庫,並且對於大表也拆分為若干小表,這樣就很大程度上降低了併發資料查詢時的資料衝突。
分表
垂直分表
定義:將一個表按照欄位分為多表,每個表裡面都儲存其中一部分欄位。
我們以商品表來舉例子:
商品資訊中,一般包括多條欄位,如商品名、價格、簡介……
而其中商品名和價格可能是最重要的,而簡介就相對沒有那麼重要。
對比兩者:
- 商品名和價格:欄位很小,請求很頻繁。
- 簡介:欄位很大,一般只有詳情頁才需要它。
大欄位都如下幾個壞處:
- 由於資料量本身大,需要更長的讀取時間
- 跨頁時,單頁內的資料行越多資料庫整體效能越好,而大欄位佔用空間大,單頁記憶體儲行數小,因此IO效率低
- 據庫以行為單位將資料載入到記憶體中,表中欄位越短,記憶體能載入的資料越多,命中率更高,減少了磁碟IO,從而提升了資料庫效能。
因此簡介這種低頻資料,會拖累商品名和價格這種高頻資料,這個時候,我們就可以將簡介從表中拆分出來。
這樣做的好處是:
-
檢視詳情的使用者與商品資訊瀏覽互不影響,避免了IO爭搶並減少鎖表的機率。
-
充分發揮高頻資料(商品名和價格)的操作效率,商品名和價格的操作的高效率不會被商品簡介的低效率所拖累。
水平分表
定義:同一個資料庫內,對資料行拆分,不影響表結構。
優點:
-
優化單一表資料量過大而產生的效能問題。
-
避免IO爭搶而減少鎖表的機率。
分庫
雖然通過分表效能得到一定程度的提升,但是很多時候還無法達到預期效果。
因為資料庫始終限制在一臺伺服器上,所以分表有如下幾個侷限性:
- 磁碟空間可能不夠。
- 只解決了單一表資料量過大的問題。
- 每個表還是競爭同一個物理機的物理資源。
垂直分庫
定義:專庫專用,按照業務將表進行分類,分佈在不同的資料庫中,每個庫可以放在不同的伺服器上
例如,我們可以將購物車表、商品表、店鋪表、買家表分在不同的伺服器中。
優點:
- 解決業務層面的耦合,業務清晰
- 能對不同業務的資料進行分級管理、維護、監控、擴充套件等
- 高併發場景下,垂直分庫一定程度的提升IO、資料庫連線數、降低單機硬體資源的瓶頸
水平分庫
隨著業務的繼續擴大,垂直分庫也將在次面臨單表過大的情況。
而已經經過了垂直分庫,我們很難再進行進一步的垂直細分,這時候就要嘗試水平分庫了。
水平分庫和水平分表十分相似,應該說就是水平分表是水平分庫的一種延續。
定義:同一個表的資料按一定規則拆到不同的資料庫中,庫放在不同的伺服器上。
優點:
-
解決了單庫大資料,高併發的效能瓶頸
-
提高了系統的穩定性及可用性
分庫分表的缺點
分頁/排序
在同一張表時,只需要用limit
、order by
便可輕鬆搞定。
跨節點多庫進行查詢時,分頁、排序,就變得很複雜。
- 先在不同的分片節點中將資料進行排序並返回
- 然後將不同分片返回的結果集進行彙總和再次排序
主鍵重複
分表分庫會讓平時經常使用的主鍵自增長形同虛設。生成的ID無法保證全域性唯一。
因此我們需要單獨設計全域性主鍵,以便面跨庫主鍵重複問題。
事務的一致性
因為分庫分表把資料分佈在不同的庫、不同伺服器,所以不可避免的帶來分散式事務問題。
當一個請求要先請求資料庫A,再請求資料庫B,這兩個屬於同一個事務,多個庫會導致分散式事務問題。
需要有一些措施來保證事務一致性的問題,這裡不在展開,有興趣自行了解。
關聯查詢
分庫後,如果兩個表不在同一個資料庫,甚至不在同一臺伺服器上,無法進行關聯查詢。
解決方案:
- 將原關聯查詢分為兩次查詢
- 第一個查詢的結果找出關聯資料id
- 根據id發起第二次請求得到關聯資料
- 最後將獲得的資料進行拼裝
總結
分庫分表的誕生是為了解決資料庫的效能瓶頸,雖然有很多好處,但相應的也有很多壞處。
但在業務量還不大的時候,我們其實應該首先考慮索引、快取、讀寫分離等方案,盲目使用分表分庫技術,會導致業務變得臃腫,反而徒增煩惱。