咱們爲何要分庫分表

本文轉自:https://baijiahao.baidu.com/s?id=1627688882923429891&wfr=spider&for=pcmysql

 

當一張表的數據達到幾千萬時,查詢一次所花的時間會變長。這時候,若是有聯合查詢的話,可能會卡死在那兒,甚至把系統給拖垮。算法

而分庫分表的目的就在於此:減少數據庫的負擔,提升數據庫的效率,縮短查詢時間。另外,由於分庫分表這種改造是可控的,底層仍是基於RDBMS,所以整個數據庫的運維體系以及相關基礎設施都是可重用的。sql

目前咱們系統將近20億數據,每張表最大的接近600w條/表,每條數據大約3k,每一個表將近1.5G的數據。查詢常常超時,單條SQL執行count(*)查詢時間達到了最大260ms,0.26s(標準是超過0.1s的數據爲慢SQL)。數據庫

爲了說明咱們爲何要分庫分表,咱們看一下sql的執行過程。服務器

mysql執行一條sql的過程以下:運維

一、收到sql數據庫設計

二、把sql放到排隊隊列中分佈式

三、執行sqlide

四、返回結果性能

在這個執行過程當中最花時間的地方在於:

1.排隊等待的時間,

2.sql的執行時間。

若是有2個sql都要同時修改同一張表的同一條數據,mysql對這種狀況的處理是:一種是表鎖定(MyISAM存儲引擎),一個是行鎖定(InnoDB存儲引擎)。

表鎖定表示其餘操做都不能對這張表進行操做,必須等當前對錶的操做完才行。行鎖定也同樣,別的sql必須等這條數據操做完了,其餘人才能對這條數據進行操做。

若是數據太多,一次執行的時間太長,等待的時間就越長,這也是咱們爲何要分表的緣由。

 

分庫分表術語:

讀寫分離: 不一樣的數據庫,同步相同的數據,分別只負責數據的讀和寫;

分區:指定分區列表達式,把記錄拆分到不一樣的區域中(必須是同一服務器,能夠是不一樣硬盤),應用看來仍是同一張表,沒有變化;

分庫:一個系統的多張數據表,存儲到多個數據庫實例中;

分表: 對於一張多行(記錄)多列(字段)的二維數據表,又分兩種情形:

垂直分表: 豎向切分,不一樣分表存儲不一樣的字段,能夠把不經常使用或者大容量、或者不一樣業務的字段拆分出去;水平分表(最複雜): 橫向切分,按照特定分片算法,不一樣分表存儲不一樣的記錄。在實際生產中,一般的進化過程是:單庫單表->單庫多表->多庫多表;;分區->分表->分庫(垂直分庫 - 水平分庫 - 讀寫分離)

單庫單表

單庫單表是最多見的數據庫設計,例如,有一張訂單表(order)放在數據庫中,全部的訂單均可以在order表中查到。

單庫多表

隨着訂單數量的增長,order表的數據量會愈來愈大,當數據量達到必定程度的時候,對order表的查詢會變慢,從而影響整個DB的性能。

另外,隨着需求的迭代,若是增長添加一列的時候,mysql會鎖表,期間全部的讀寫操做只能等待,別無他法。

這時候,能夠將order進行水平的切分,產生多個表結構徹底同樣的order表。好比:order_01,order_02....,order_n,那麼order_01+order_02+order_n的數據是一份完整的訂單數據。

這個水平切分,簡單的作法如:

按數量切分,1~1000的存在第一張表,1001~2000存在第二張表;

按時間切分,好比:2019年1月份存在第一張表,2019年2月份存在第二張表;還能夠按照id的哈希值進行切分,等等等等

多庫多表

隨着數據量增長,單臺數據庫的硬件存儲不夠了,而且,隨着查詢量的增長,單臺數據庫服務器已經沒辦法支撐。這時候就須要對數據庫進行水平區分。

好比按地區分庫,一個省份在一個物理數據庫等等

任何事情都有兩面性,分庫分表也不例外,若是採用分庫分表,會引入新的的問題

1.分佈式事務問題

作了垂直分庫或者水平分庫之後,就必然會涉及到跨庫執行SQL的問題,就會引起互聯網界的老大難問題-"分佈式事務"。那麼要如何解決這個問題呢?

使用分佈式事務中間件使用MySQL自帶的針對跨庫的事務一致性方案(XA),不過性能要比單庫的慢10倍左右。可否避免掉跨庫操做(好比將用戶和商品放在同一個庫中)2.跨庫join的問題

分庫分表後,表之間的關聯操做將受到限制,就沒法join位於不一樣分庫的表,也沒法join分表粒度不一樣的表, 結果本來一次查詢可以完成的業務,可能須要屢次查詢才能完成。

那麼要如何解決這個問題呢?

簡單的解決方法:

全局表:基礎數據,全部庫都拷貝一份。字段冗餘:把須要join的字段冗餘在各個表中,這樣有些字段就不用join去查詢了。系統層組裝:應用端先分別查詢出全部複覈條件的,而後在應用端組裝起來,相似於一個mapreduce的過程(較複雜)。3.橫向擴容的問題

當咱們使用哈希取模作分表的時候,針對數據量的遞增,可能須要動態的增長表,此時就須要考慮數據遷移的問題。

原來使用的是hash後對8進行取模,那麼,數據是均分在8個表(庫)上。

若是8個表不夠的時候,咱們要擴展到16個表,這時候,咱們hash後對16取模,新數據是沒有問題的,舊數據就會發生錯亂。

若是哈希後是9,那麼,原來咱們對8取模後,是1,會到表1進行查詢;可是,如今咱們是對16取模,那麼是到表9進行查詢的,而這個數據在表9又不存在,所以,就會找不到數據了

4.結果集合並、排序的問題

由於咱們是將數據分散存儲到不一樣的庫、表裏的,當咱們查詢指定數據列表時,數據來源於不一樣的子庫或者子表,就必然會引起結果集合並、排序的問題。

若是每次查詢都須要排序、合併等操做,性能確定會受很是大的影響。

上面列出了分庫分表的常見的一些,總的來講:

能不切分儘可能不要切分,若是沒有達到幾百萬,一般無需分庫分表若是必定要切分,必定要選擇合適的切分規則,提早規劃好。若是必定要切分,儘可能經過數據冗餘或表分組來下降跨庫 Join 的可能。對於如今市面上有好幾種數據庫中間件,這些中間件對數據 Join 實現,箇中滋味,只能本身體會。業務讀取儘可能少使用多表 Join。數據儘量的比較均勻分佈數據到各個節點上

相關文章
相關標籤/搜索