【科普】談談分庫分表與分片
一. 大綱
在談論資料庫架構和資料庫優化的時候,我們經常會聽到分庫分表
、分割槽
、分片(Sharding)
等關鍵詞,對於這些概念,相信大家應該都有聽說過或是瀏覽過相關的文件,我們今天就來詳細瞭解下這幾個比較容易混淆的概念。
首先呢,我們需要知道上述的這些方案都是為了同一個目的
而產生,那就是為了突破單表/庫過大
或單節點資料庫伺服器
的效能瓶頸,解決資料庫的擴充套件性問題。
因為隨著表資料量的增長,單機資料庫的資源和處理能力有限,所以資料庫非常容易成為應用系統的瓶頸。
二. 分庫
垂直分庫
在微服務
盛行的今天已經非常普及了,基本的思路就是按照業務模組
來劃分出不同的資料庫,而不是像早期一樣將所有的資料表都放到同一個資料庫中。
系統層面的服務化
拆分能夠解決業務系統層面的耦合
與效能瓶頸
,有利於系統的擴充套件維護。
而資料庫層面的資料拆分,道理其實也是相通的,可以更加便於資料庫的管理、維護、監控、擴充套件
等。
垂直分庫
可以在一定程度上解決資料庫單機瓶頸,因為可以將不同的業務庫分散在不同的伺服器上,獨享資源,互不干擾,但是一定要了解清楚拆分的原則與技巧,否則會遇到很多問題,例如:跨庫JOIN
、分散式事務
等。
三. 分表
分表
就是將一張大表
拆分成N個子表
,根據切分規則,通常由如下兩種模式:
-
垂直拆分:基於
列
拆分表,將表中的某些欄位拆分出去放入到擴充套件表
中。 -
水平拆分:基於
行
拆分表,通過規則匹配分類後,將資料放到若干個子表
3.1. 垂直分表
垂直分表
在日常開發和設計中比較常見,通俗的說法叫做大表拆小表
,拆分是基於關係型資料庫中的列(欄位)
進行的。
通常情況下,當某個表中的欄位比較多時,可以新建一張擴充套件表
,將不經常使用或者長度較大的欄位拆分出去。
垂直分表的作用比較有限,它只可以減少行資料大小,加快資料檢索的速度,但是無法解決因為表資料量增長而導致的壓力。
表字段拆分(垂直分表)
建議在資料庫設計階段就做好,如果是在發展過程中拆分,則需要改寫以前的查詢語句,會額外帶來一定的成本和風險。
3.2. 水平分表
水平分表
也稱為橫向分表
,就是將表中不同的資料行按照一定規律分佈到不同的資料庫表中(這些表儲存在同一個資料庫中
這種同庫下水平分表通常有以下幾張方式:
-
冷熱資料分離:
-
定期將使用較少的歷史資料遷移到對應的歷史表中,減少原表的資料量。
-
-
業務分表:
-
在程式碼層面實現分表,資料庫中存在多張子表,但在應用上層表現為一張表。
-
-
分割槽表:
-
通過資料庫自帶的分割槽表功能實現分表,邏輯上表現為一張表,但是底層儲存在不同的分割槽上。
-
水平分表
能夠降低單表的資料量(分割槽表必須要帶上分割槽條件才可以提前過濾
),一定程度上緩解查詢效能瓶頸。但本質上這些表還是儲存在同一個庫,或者說同一個資料庫例項、同一個DB伺服器中,所以無法避免單機資料庫效能瓶頸的問題。
四. 分片
分片
也叫做Sharding
,或是水平分庫分表
,都是相同的概念,與上面所講到的水平分表的概念類似,唯一不同點
就在於將這些拆分出來的子表儲存在不同的資料庫伺服器
中。
常見分片策略
:
-
RANGE:按照範圍劃分,比如按照日期或者自增鍵進行範圍劃分。
-
HASH: 採用 hash+mod 的組合劃分資料。
分片實現方式
:
-
客戶端:
-
在客戶端實現分片,如比較流行的
分庫分表框架Sharding-JDBC
,就是在驅動層
實現了分片功能,對上層應用保持透明。
-
-
中間層:
-
通過在應用與DB之間接入
中介軟體(Proxy)
,如DBLE、MaxScale等開源中介軟體,用於實現後端資料分片與路由查詢,對上層應用保持透明。
-
-
服務端:
-
使用某些
分散式資料庫
,如TiDB、SequoiaDB等開源NewSQL,其在儲存引擎層
實現了資料分片功能,對上層應用保持透明。
-
分片能夠有效的緩解單機、單庫、單表的效能瓶頸,突破IO、連線數、硬體資源等瓶頸。但是我們一旦將資料分片後,那麼整個資料庫架構就轉換成了分散式架構
,也會引發諸多問題:
-
分散式事務
:-
資料分片後,原先的
本地事務
就演變成了分散式事務
了,一般需要通過二階段或三階段提交
來保證分散式事務的ACID特性,效能也因此會有一定損耗。
-
-
跨庫join
:-
分庫分表後,不同的表分佈在不同的伺服器上,所以無法直接通過sql join來進行查詢,這時候通常會建立
冗餘欄位
或全域性表
來實現跨庫join。
-
-
SQL問題
:-
資料分片後,SQL的執行需要分發到各個節點計算,然後將結果合併後再返回,
效能會有所下降
,並且當SQL較為複雜時,結果準確性
也有可能出現問題。這個問題也是資料分片實現中最為關鍵的點,只能不斷優化完善,無法完全解決。
-
-
自增主鍵
:-
資料分片後,我們將不能再依賴資料庫自身的自增鍵生成機制,需要配置額外的
全域性序列
來保證自增主鍵的全域性唯一。
-
五. 小結
需要注意的是,分片(Sharding)
會為資料庫維護和業務邏輯帶來一系列複雜性和效能損耗,所以除非業務量大到萬不得已,否則切莫過度設計
、過早優化
。
面對資料庫效能問題,我們可以先嚐試用以下方式來解決:
-
資料優化:優化SQL、索引及相關資料庫引數配置。
-
硬體擴充套件:提升伺服器CPU、記憶體、磁碟IOPS等硬體配置。
-
讀寫分離:通過讀寫分離架構提高資料庫的整體效能。
-
資料拆分:通過垂直拆分庫表,或水平分表來解決大表效能問題
如果上述方式仍未能奏效,才考慮最複雜的方案:資料分片