【科普】談談分庫分表與分片


一. 大綱

在談論數據庫架構和數據庫優化的時候,我們經常會聽到分庫分表分區分片(Sharding)等關鍵詞,對於這些概念,相信大家應該都有聽說過或是瀏覽過相關的文檔,我們今天就來詳細了解下這幾個比較容易混淆的概念。

首先呢,我們需要知道上述的這些方案都是為了同一個目的而產生,那就是為了突破單表/庫過大單節點數據庫服務器的性能瓶頸,解決數據庫的擴展性問題。

因為隨着表數據量的增長,單機數據庫的資源和處理能力有限,所以數據庫非常容易成為應用系統的瓶頸。

二. 分庫

垂直分庫微服務盛行的今天已經非常普及了,基本的思路就是按照業務模塊來划分出不同的數據庫,而不是像早期一樣將所有的數據表都放到同一個數據庫中。

系統層面的服務化拆分能夠解決業務系統層面的耦合性能瓶頸,有利於系統的擴展維護。

而數據庫層面的數據拆分,道理其實也是相通的,可以更加便於數據庫的管理、維護、監控、擴展等。

垂直分庫可以在一定程度上解決數據庫單機瓶頸,因為可以將不同的業務庫分散在不同的服務器上,獨享資源,互不干擾,但是一定要了解清楚拆分的原則與技巧,否則會遇到很多問題,例如:跨庫JOIN分布式事務等。

三. 分表

分表就是將一張大表拆分成N個子表,根據切分規則,通常由如下兩種模式:

  • 垂直拆分:基於拆分表,將表中的某些字段拆分出去放入到擴展表中。

  • 水平拆分:基於拆分表,通過規則匹配分類后,將數據放到若干個子表中。

3.1. 垂直分表

垂直分表在日常開發和設計中比較常見,通俗的說法叫做大表拆小表,拆分是基於關系型數據庫中的列(字段)進行的。

通常情況下,當某個表中的字段比較多時,可以新建一張擴展表,將不經常使用或者長度較大的字段拆分出去。

垂直分表的作用比較有限,它只可以減少行數據大小,加快數據檢索的速度,但是無法解決因為表數據量增長而導致的壓力。

表字段拆分(垂直分表)建議在數據庫設計階段就做好,如果是在發展過程中拆分,則需要改寫以前的查詢語句,會額外帶來一定的成本和風險。

3.2. 水平分表

水平分表也稱為橫向分表,就是將表中不同的數據行按照一定規律分布到不同的數據庫表中(這些表保存在同一個數據庫中),以此來降低單表數據量,優化查詢性能。

這種同庫下水平分表通常有以下幾張方式:

  1. 冷熱數據分離:

    • 定期將使用較少的歷史數據遷移到對應的歷史表中,減少原表的數據量。

  2. 業務分表:

    • 在代碼層面實現分表,數據庫中存在多張子表,但在應用上層表現為一張表。

  3. 分區表:

    • 通過數據庫自帶的分區表功能實現分表,邏輯上表現為一張表,但是底層存儲在不同的分區上。



水平分表能夠降低單表的數據量(分區表必須要帶上分區條件才可以提前過濾),一定程度上緩解查詢性能瓶頸。但本質上這些表還是保存在同一個庫,或者說同一個數據庫實例、同一個DB服務器中,所以無法避免單機數據庫性能瓶頸的問題。

四. 分片

分片也叫做Sharding,或是水平分庫分表,都是相同的概念,與上面所講到的水平分表的概念類似,唯一不同點就在於將這些拆分出來的子表保存在不同的數據庫服務器中。



常見分片策略

  1. RANGE:按照范圍划分,比如按照日期或者自增鍵進行范圍划分。

  1. HASH: 采用 hash+mod 的組合划分數據。

分片實現方式

  1. 客戶端:

    • 在客戶端實現分片,如比較流行的分庫分表框架Sharding-JDBC,就是在驅動層實現了分片功能,對上層應用保持透明。

  2. 中間層:

    • 通過在應用與DB之間接入中間件(Proxy),如DBLE、MaxScale等開源中間件,用於實現后端數據分片與路由查詢,對上層應用保持透明。

  3. 服務端:

    • 使用某些分布式數據庫,如TiDB、SequoiaDB等開源NewSQL,其在存儲引擎層實現了數據分片功能,對上層應用保持透明。

分片能夠有效的緩解單機、單庫、單表的性能瓶頸,突破IO、連接數、硬件資源等瓶頸。但是我們一旦將數據分片后,那么整個數據庫架構就轉換成了分布式架構,也會引發諸多問題:

  1. 分布式事務:

    • 數據分片后,原先的本地事務就演變成了分布式事務了,一般需要通過二階段或三階段提交來保證分布式事務的ACID特性,性能也因此會有一定損耗。

     

  2. 跨庫join:

    • 分庫分表后,不同的表分布在不同的服務器上,所以無法直接通過sql join來進行查詢,這時候通常會建立冗余字段全局表來實現跨庫join。

     

  3. SQL問題:

    • 數據分片后,SQL的運行需要分發到各個節點計算,然后將結果合並后再返回,性能會有所下降,並且當SQL較為復雜時,結果准確性也有可能出現問題。這個問題也是數據分片實現中最為關鍵的點,只能不斷優化完善,無法完全解決。

     

  4. 自增主鍵:

    • 數據分片后,我們將不能再依賴數據庫自身的自增鍵生成機制,需要配置額外的全局序列來保證自增主鍵的全局唯一。

五. 小結

需要注意的是,分片(Sharding)會為數據庫維護和業務邏輯帶來一系列復雜性和性能損耗,所以除非業務量大到萬不得已,否則切莫過度設計過早優化

面對數據庫性能問題,我們可以先嘗試用以下方式來解決:

  1. 數據優化:優化SQL、索引及相關數據庫參數配置。

  2. 硬件擴展:提升服務器CPU、內存、磁盤IOPS等硬件配置。

  3. 讀寫分離:通過讀寫分離架構提高數據庫的整體性能。

  4. 數據拆分:通過垂直拆分庫表,或水平分表來解決大表性能問題

如果上述方式仍未能奏效,才考慮最復雜的方案:數據分片


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM