Echarts 在地圖上繪製流向圖
分庫分表是什麼
下邊以電商系統中的例子來說明,下圖是電商系統賣家模組的表結構:
通過以下SQL能夠獲取到商品相關的店鋪資訊、地理區域資訊:
SELECT p.*,r.[地理區域名稱],s.[店鋪名稱],s.[信譽]
FROM [商品資訊] p
LEFT JOIN [地理區域] r ON p.[產地] = r.[地理區域編碼]
LEFT JOIN [店鋪資訊] s ON s.id = p.[所屬店鋪]
WHERE p.id = ?
1
2
3
4
5
隨著公司業務快速發展,資料庫中的資料量猛增,訪問效能也變慢了,優化迫在眉睫。分析一下問題出現在哪兒呢? 關係型資料庫本身比較容易成為系統瓶頸,單機儲存容量、連線數、處理能力都有限。當單表的資料量達到1000W或100G以後,由於查詢維度較多,即使新增從庫、優化索引,做很多操作時效能仍下降嚴重。
方案1:
通過提升伺服器硬體能力來提高資料處理能力,比如增加儲存容量 、CPU等,這種方案成本很高,並且如果瓶頸在MySQL本身那麼提高硬體也是有很的。
方案2:
把資料分散在不同的資料庫中,使得單一資料庫的資料量變小來緩解單一資料庫的效能問題,從而達到提升資料庫效能的目的,如下圖:將電商資料庫拆分為若干獨立的資料庫,並且對於大表也拆分為若干小表,通過這種資料庫拆分的方法來解決資料庫的效能問題。
分庫分表就是為了解決由於資料量過大而導致資料庫效能降低的問題,將原來獨立的資料庫拆分成若干資料庫組成 ,將資料大表拆分成若干資料表組成,使得單一資料庫、單一資料表的資料量變小,從而達到提升資料庫效能的目的。
垂直分表
分庫分表包括分庫和分表兩個部分,在生產中通常包括:垂直分庫、水平分庫、垂直分表、水平分表四種方式。
先說 垂直分表:
通常在商品列表中是不顯示商品詳情資訊的,如下圖:
使用者在瀏覽商品列表時,只有對某商品感興趣時才會檢視該商品的詳細描述。因此,商品資訊中商品描述欄位訪問頻次較低,且該欄位儲存佔用空間較大,訪問單個數據IO時間較長;商品資訊中商品名稱、商品圖片、商品價格等其他欄位資料訪問頻次較高。
由於這兩種資料的特性不一樣,因此他考慮將商品資訊表拆分如下:
將訪問頻次低的商品描述資訊單獨存放在一張表中,訪問頻次較高的商品基本資訊單獨放在一張表中。
商品列表可採用以下sql:
SELECT p.*,r.[地理區域名稱],s.[店鋪名稱],s.[信譽]
FROM [商品資訊] p
LEFT JOIN [地理區域] r ON p.[產地] = r.[地理區域編碼]
LEFT JOIN [店鋪資訊] s ON s.id = p.[所屬店鋪]
WHERE...ORDER BY...LIMIT...
1
2
3
4
5
需要獲取商品描述時,再通過以下sql獲取:
SELECT *
FROM [商品描述]
WHERE [商品ID] = ?
1
2
3
垂直分表定義:將一個表按照欄位分成多表,每個表儲存其中一部分欄位。
它帶來的提升是:
1.為了避免IO爭搶並減少鎖表的機率,檢視詳情的使用者與商品資訊瀏覽互不影響
2.充分發揮熱門資料的操作效率,商品資訊的操作的高效率不會被商品描述的低效率所拖累。
為什麼大欄位IO效率低:第一是由於資料量本身大,需要更長的讀取時間;第二是跨頁,頁是資料庫儲存單位,很多查詢及定位操作都是以頁為單位,單頁內的資料行越多資料庫整體效能越好,而大欄位佔用空間大,單頁記憶體儲行數少,因此IO效率較低。第三,資料庫以行為單位將資料載入到記憶體中,這樣表中欄位長度較短且訪問頻率較高,記憶體能載入更多的資料,命中率更高,減少了磁碟IO,從而提升了資料庫效能。
一般來說,某業務實體中的各個資料項的訪問頻次是不一樣的,部分資料項可能是佔用儲存空間比較大的BLOB或是TEXT。例如上例中的商品描述。所以,當表資料量很大時,可以將表按欄位切開,將熱門欄位、冷門欄位分開放置在不同庫中,這些庫可以放在不同的儲存裝置上,避免IO爭搶。垂直切分帶來的效能提升主要集中在熱門資料的操作效率上,而且磁碟爭用情況減少。
通常我們按以下原則進行垂直拆分:
把不常用的欄位單獨放在一張表;
把text,blob等大欄位拆分出來放在附表中;
經常組合查詢的列放在一張表中;
垂直分庫
通過垂直分表效能得到了一定程度的提升,但是還沒有達到要求,並且磁碟空間也快不夠了,因為資料還是始終限制在一臺伺服器,庫內垂直分表只解決了單一表資料量過大的問題,但沒有將表分佈到不同的伺服器上,因此每個表還是競爭同一個物理機的CPU、記憶體、網路IO、磁碟。
經過思考,他把原有的SELLER_DB(賣家庫),分為了PRODUCT_DB(商品庫)和STORE_DB(店鋪庫),並把這兩個庫分散到不同伺服器,如下圖:
由於商品資訊與商品描述業務耦合度較高,因此一起被存放在PRODUCT_DB(商品庫);而店鋪資訊相對獨立,因此單獨被存放在STORE_DB(店鋪庫)。
垂直分庫是指按照業務將表進行分類,分佈到不同的資料庫上面,每個庫可以放在不同的伺服器上,它的核心理念是專庫專用。
它帶來的提升是:
解決業務層面的耦合,業務清晰
能對不同業務的資料進行分級管理、維護、監控、擴充套件等
高併發場景下,垂直分庫一定程度的提升IO、資料庫連線數、降低單機硬體資源的瓶頸
垂直分庫通過將表按業務分類,然後分佈在不同資料庫,並且可以將這些資料庫部署在不同伺服器上,從而達到多個伺服器共同分攤壓力的效果,但是依然沒有解決單表資料量過大的問題。
水平分庫
經過垂直分庫後,資料庫效能問題得到一定程度的解決,但是隨著業務量的增長,PRODUCT_DB(商品庫)單庫儲存資料已經超出預估。粗略估計,目前有8w店鋪,每個店鋪平均150個不同規格的商品,再算上增長,那商品數量得往1500w+上預估,並且PRODUCT_DB(商品庫)屬於訪問非常頻繁的資源,單臺伺服器已經無法支撐。此時該如何優化?
再次分庫?但是從業務角度分析,目前情況已經無法再次垂直分庫。
嘗試水平分庫,將店鋪ID為單數的和店鋪ID為雙數的商品資訊分別放在兩個庫中。
也就是說,要操作某條資料,先分析這條資料所屬的店鋪ID。如果店鋪ID為雙數,將此操作對映至RRODUCT_DB1(商品庫1);如果店鋪ID為單數,將操作對映至RRODUCT_DB2(商品庫2)。此操作要訪問資料庫名稱的表示式為RRODUCT_DB[店鋪ID%2 + 1] 。
水平分庫是把同一個表的資料按一定規則拆到不同的資料庫中,每個庫可以放在不同的伺服器上。
垂直分庫是把不同表拆到不同資料庫中,它是對資料行的拆分,不影響表結構
它帶來的提升是:
解決了單庫大資料,高併發的效能瓶頸。
提高了系統的穩定性及可用性。
穩定性體現在IO衝突減少,鎖定減少,可用性指某個庫出問題,部分可用`
當一個應用難以再細粒度的垂直切分,或切分後資料量行數巨大,存在單庫讀寫、儲存效能瓶頸,這時候就需要進行水平分庫了,經過水平切分的優化,往往能解決單庫儲存量及效能瓶頸。但由於同一個表被分配在不同的資料庫,需要額外進行資料操作的路由工作,因此大大提升了系統複雜度。
水平分表
按照水平分庫的思路對他把PRODUCT_DB_X(商品庫)內的表也可以進行水平拆分,其目的也是為解決單表資料量大的問題,如下圖:
與水平分庫的思路類似,不過這次操作的目標是表,商品資訊及商品描述被分成了兩套表。如果商品ID為雙數,將此操作對映至商品資訊1表;如果商品ID為單數,將操作對映至商品資訊2表。此操作要訪問表名稱的表示式為商品資訊[商品ID%2 + 1] 。
水平分表是在同一個資料庫內,把同一個表的資料按一定規則拆到多個表中。
它帶來的提升是:
優化單一表資料量過大而產生的效能問題
避免IO爭搶並減少鎖表的機率
庫內的水平分表,解決了單一表資料量過大的問題,分出來的小表中只包含一部分資料,從而使得單個表的資料量變小,提高檢索效能。
總結
垂直分表:可以把一個寬表的欄位按訪問頻次、是否是大欄位的原則拆分為多個表,這樣既能使業務清晰,還能提升部分效能。拆分後,儘量從業務角度避免聯查,否則效能方面將得不償失。
垂直分庫:可以把多個表按業務耦合鬆緊歸類,分別存放在不同的庫,這些庫可以分佈在不同伺服器,從而使訪問壓力被多伺服器負載,大大提升效能,同時能提高整體架構的業務清晰度,不同的業務庫可根據自身情況定製優化方案。但是它需要解決跨庫帶來的所有複雜問題。
水平分庫:可以把一個表的資料(按資料行)分到多個不同的庫,每個庫只有這個表的部分資料,這些庫可以分佈在不同伺服器,從而使訪問壓力被多伺服器負載,大大提升效能。它不僅需要解決跨庫帶來的所有複雜問題,還要解決資料路由的問題(資料路由問題後邊介紹)。
水平分表:可以把一個表的資料(按資料行)分到多個同一個資料庫的多張表中,每個表只有這個表的部分資料,這樣做能小幅提升效能,它僅僅作為水平分庫的一個補充優化。
一般來說,在系統設計階段就應該根據業務耦合鬆緊來確定垂直分庫,垂直分表方案,在資料量及訪問壓力不是特別大的情況,首先考慮快取、讀寫分離、索引技術等方案。若資料量極大,且持續增長,再考慮水平分庫水平分表方案。
————————————————
版權宣告:本文為CSDN博主「傳智燕青」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處連結及本宣告。
原文連結:https://blog.csdn.net/weixin_44062339/article/details/100491744