當一張表的數據達到幾千萬時,查詢一次所花的時間會變長。業界公認MySQL單表容量在 1千萬 如下是最佳狀態,由於這時它的BTREE索引樹高在3~5之間。html
數據切分能夠分爲:垂直切分
和水平切分
。mysql
垂直切分又能夠分爲: 垂直分庫
和垂直分表
。算法
概念
就是根據業務耦合性,將關聯度低的不一樣表存儲在不一樣的數據庫。作法與大系統拆分爲多個小系統相似,按業務分類進行獨立劃分。與"微服務治理"的作法類似,sql
每一個微服務使用單獨的一個數據庫。數據庫
如圖:併發
說明
負載均衡
一開始咱們是單體服務,因此只有一個數據庫,全部的表都在這個庫裏。分佈式
後來由於業務需求,單體服務變成微服務治理。因此將以前的一個商品庫,拆分紅多個數據庫。每一個微服務對於一個數據庫。ide
概念
把一個表的多個字段分別拆成多個表,通常按字段的冷熱拆分,熱字段一個表,冷字段一個表。從而提高了數據庫性能。函數
如圖:
說明
一開始商品表中包含商品的全部字段,可是咱們發現:
1.商品詳情和商品屬性字段較長
。2.商品列表的時候咱們是不須要顯示商品詳情和商品屬性信息,只有在點進商品商品的時候纔會展現商品詳情信息
。
因此能夠考慮把商品詳情和商品屬性單獨切分一張表,提升查詢效率。
優勢
- 解決業務系統層面的耦合,業務清晰 - 與微服務的治理相似,也能對不一樣業務的數據進行分級管理、維護、監控、擴展等 - 高併發場景下,垂直切分必定程度的提高IO、數據庫鏈接數、單機硬件資源的瓶頸
缺點
- 分庫後沒法Join,只能經過接口聚合方式解決,提高了開發的複雜度 - 分庫後分布式事務處理複雜 - 依然存在單表數據量過大的問題(須要水平切分)
當一個應用難以再細粒度的垂直切分或切分後數據量行數巨大,存在單庫讀寫、存儲性能瓶頸,這時候就須要進行水平切分了。
水平切分也能夠分爲:水平分庫
和水平分表
。
水平分庫的緣由
上面雖然已經把商品庫分紅3個庫,可是隨着業務的增長一個訂單庫也出現QPS太高,數據庫響應速度來不及,通常mysql單機也就1000左右的QPS,若是超過1000就要考慮分庫。
如圖
概念
通常咱們一張表的數據不要超過1千萬,若是表數據超過1千萬,而且還在不斷增長數據,那就能夠考慮分表。
如圖
優勢
- 不存在單庫數據量過大、高併發的性能瓶頸,提高系統穩定性和負載能力 - 應用端改造較小,不須要拆分業務模塊
缺點
- 跨分片的事務一致性難以保證 - 跨庫的Join關聯查詢性能較差 - 數據屢次擴展難度和維護量極大
咱們咱們考慮去水平切分表,將一張表水平切分紅多張表,這就涉及到數據分片的規則,比較常見的有:Hash取模分表
、數值Range分表
、一致性Hash算法分表
。
概念
通常採用Hash取模的切分方式,例如:假設按goods_id分4張表。(goods_id%4 取整肯定表)
優勢
- 數據分片相對比較均勻,不容易出現熱點和併發訪問的瓶頸。
缺點
- 後期分片集羣擴容時,須要遷移舊的數據很難。 - 容易面臨跨分片查詢的複雜問題。好比上例中,若是頻繁用到的查詢條件中不帶goods_id時,將會致使沒法定位數據庫,從而須要同時向4個庫發起查詢, 再在內存中合併數據,取最小集返回給應用,分庫反而成爲拖累。
概念
按照時間區間或ID區間來切分。例如:將goods_id爲1~1000的記錄分到第一個表,1001~2000的分到第二個表,以此類推。
如圖
優勢
- 單表大小可控 - 自然便於水平擴展,後期若是想對整個分片集羣擴容時,只須要添加節點便可,無需對其餘分片的數據進行遷移 - 使用分片字段進行範圍查找時,連續分片可快速定位分片進行快速查詢,有效避免跨分片查詢的問題。
缺點
- 熱點數據成爲性能瓶頸。 例如按時間字段分片,有些分片存儲最近時間段內的數據,可能會被頻繁的讀寫,而有些分片存儲的歷史數據,則不多被查詢
一致性Hash算法能很好的解決由於Hash取模而產生的分片集羣擴容時,須要遷移舊的數據的難題
。至於具體原理這裏就不詳細說,
能夠參考一篇博客:一致性哈希算法(分庫分表,負載均衡等)
任何事情都有兩面性,分庫分表也不例外,若是採用分庫分表,會引入新的的問題
使用分佈式事務中間件解決,具體是經過最終一致性仍是強一致性分佈式事務,看業務需求,這裏就很少說。
切分以前,咱們能夠經過Join來完成。而切分以後,數據可能分佈在不一樣的節點上,此時Join帶來的問題就比較麻煩了,考慮到性能,儘可能避免使用Join查詢。
解決這個問題的一些方法:
全局表
全局表,也可看作是 "數據字典表",就是系統中全部模塊均可能依賴的一些表,爲了不跨庫Join查詢,能夠將 這類表在每一個數據庫中都保存一份。這些數據一般
不多會進行修改,因此也不擔憂一致性的問題。
字段冗餘
利用空間換時間,爲了性能而避免join查詢。例:訂單表保存userId時候,也將userName冗餘保存一份,這樣查詢訂單詳情時就不須要再去查詢"買家user表"了。
數據組裝
在系統層面,分兩次查詢。第一次查詢的結果集中找出關聯數據id,而後根據id發起第二次請求獲得關聯數據。最後將得到到的數據進行字段拼裝。
跨節點多庫進行查詢時,會出現Limit分頁、Order by排序等問題。分頁須要按照指定字段進行排序,當排序字段就是分片字段時,經過分片規則就比較容易定位到指定的分片;
當排序字段非分片字段時,就變得比較複雜了。須要先在不一樣的分片節點中將數據進行排序並返回,而後將不一樣分片返回的結果集進行彙總和再次排序,最終返回給用戶。
若是都用主鍵自增
確定不合理,若是用UUID
那麼沒法作到根據主鍵排序,因此咱們能夠考慮經過雪花ID
來做爲數據庫的主鍵,
有關雪花ID能夠參考我以前寫的博客:靜態內部類單例模式實現雪花算法
採用雙寫的方式
,修改代碼,全部涉及到分庫分表的表的增、刪、改的代碼,都要對新庫進行增刪改。同時,再有一個數據抽取服務,不斷地從老庫抽數據,往新庫寫,
邊寫邊按時間比較數據是否是最新的。
一、分庫分表
二、談談分庫分表吧?
我相信,不管從此的道路多麼坎坷,只要抓住今天,早晚會在奮鬥中嚐到人生的甘甜。抓住人生中的一分一秒,賽過虛度中的一月一年!(16)