1. 程式人生 > >分表、分庫、分片和分割槽

分表、分庫、分片和分割槽

轉載:用sharding技術來擴充套件你的資料庫(一)sharding 介紹

轉載:MySQL架構方案 - Scale Out & Scale Up.

轉載: 資料表分割槽策略及實現(一)

轉載:Mysql分表和分割槽的區別、分庫分表介紹與區別

轉載:分庫分錶帶來的完整性和一致性問題

轉載:開源資料庫 Sharding 技術 (Share Nothing)

一、Sharding(分片)

Sharding 是把資料庫橫向擴充套件(Scale Out)到多個物理節點上的一種有效的方式,其主要目的是為突破單節點資料庫伺服器的 I/O 能力限制,解決資料庫擴充套件性問題

。Shard這個詞的意思是“碎片”。如果將一個數據庫當作一塊大玻璃,將這塊玻璃打碎,那麼每一小塊都稱為資料庫的碎片(DatabaseShard)。將整個資料庫打碎的過程就叫做sharding,可以翻譯為分片

形式上,Sharding可以簡單定義為將大資料庫分佈到多個物理節點上的一個分割槽方案。每一個分割槽包含資料庫的某一部分,稱為一個shard,分割槽方式可以是任意的,並不侷限於傳統的水平分割槽和垂直分割槽。一個shard可以包含多個表的內容甚至可以包含多個數據庫例項中的內容。每個shard被放置在一個數據庫伺服器上。一個數據庫伺服器可以處理一個或多個shard的資料。系統中需要有伺服器進行查詢路由轉發,負責將查詢轉發到包含該查詢所訪問資料的shard或shards節點上去執行。

二、Scale Out/Scale Up 和 垂直切分/水平拆分

Mysql的擴充套件方案包括Scale Out和Scale Up兩種

  1. Scale Out(橫向擴充套件)是指Application可在水平方向擴充套件。當新增更多的機器的資源來提升自己的效率從而達到很好的擴充套件性。
  2. Scale Up(縱向擴充套件)是指Application可以在垂直方向擴充套件。對單臺機器而言,(提升單機硬體)Scale Up值得是當某個計算節點(機器)新增更多的CPU Cores,儲存裝置,使用更大的記憶體時,應用可以很充分的利用這些資源來提升自己的效率從而達到很好的擴充套件性

MySql的Sharding策略包括垂直切分和水平切分兩種

  1. 垂直(縱向)拆分:按功能模組拆分,解決表與表之間的io競爭。如分為訂單庫、商品庫、使用者庫...多個數據庫之間的表結構不同。
  2. 水平(橫向)拆分:將同一個表的資料進行分塊儲存到不同的資料庫中,來解決單表中資料量增長出現的壓力。這些資料庫中的表結構完全相同

 

表結構設計垂直切分。常見的一些場景包括

  • a). 大欄位的垂直切分。單獨將大欄位建在另外的表中,提高基礎表的訪問效能,原則上在效能關鍵的應用中應當避免資料庫的大欄位
  • b). 按照使用用途垂直切分。例如企業物料屬性,可以按照基本屬性、銷售屬性、採購屬性、生產製造屬性、財務會計屬性等用途垂直切分
  • c). 按照訪問頻率垂直切分。例如電子商務、Web 2.0系統中,如果使用者屬性設定非常多,可以將基本、使用頻繁的屬性和不常用的屬性垂直切分開

 

表結構設計水平切分。常見的一些場景包括

  • a). 比如線上電子商務網站,訂單表資料量過大,按照年度、月度水平切分
  • b). Web 2.0網站註冊使用者、線上活躍使用者過多,按照使用者ID範圍等方式,將相關使用者以及該使用者緊密關聯的表做水平切分
  • c). 例如論壇的置頂帖子,因為涉及到分頁問題,每頁都需要顯示置頂貼,這種情況可以把置頂貼水平切分開來,避免取置頂帖子時從所有帖子的表中讀取

 

三、分表和分割槽

  • 分表從表面意思說就是把一張表分成多個小表
  • 分割槽則是把一張表的資料分成N多個區塊,這些區塊可以在同一個磁碟上,也可以在不同的磁碟上。

分表和分割槽的區別:

1,實現方式上 

mysql的分表是真正的分表,一張表分成很多表後,每一個小表都是完正的一張表,都對應三個檔案(MyISAM引擎:一個.MYD資料檔案,.MYI索引檔案,.frm表結構檔案)。

2,資料處理上 

分表後資料都是存放在分表裡,總表只是一個外殼,存取資料發生在一個一個的分表裡面。分割槽則不存在分表的概念,分割槽只不過把存放資料的檔案分成了許多小塊,分割槽後的表還是一張表,資料處理還是由自己來完成。

3,提高效能上 

 分表後,單表的併發能力提高了,磁碟I/O效能也提高了。分割槽突破了磁碟I/O瓶頸,想提高磁碟的讀寫能力,來增加mysql效能。 

在這一點上,分割槽和分表的測重點不同,

  • 分表重點是存取資料時,如何提高mysql併發能力上。
  • 分割槽重點在於如何突破磁碟的讀寫能力,從而達到提高mysql效能的目的。 

4,實現的難易度上 

分表的方法有很多,用merge來分表,是最簡單的一種方式。這種方式和分割槽難易度差不多,並且對程式程式碼來說可以做到透明的。如果是用其他分表方式就比分割槽麻煩了。 分割槽實現是比較簡單的,建立分割槽表,跟建平常的表沒什麼區別,並且對程式碼端來說是透明的。 

分割槽的適用場景

  •  一張表的查詢速度已經慢到影響使用的時候。
  • 表中的資料是分段的
  • 對資料的操作往往只涉及一部分資料,而不是所有的資料
  1. CREATE TABLE sales (

  2. id INT AUTO_INCREMENT,

  3. amount DOUBLE NOT NULL,

  4. order_day DATETIME NOT NULL,

  5. PRIMARY KEY(id, order_day)

  6. ) ENGINE=Innodb

  7. PARTITION BY RANGE(YEAR(order_day)) (

  8. PARTITION p_2010 VALUES LESS THAN (2010),

  9. PARTITION p_2011 VALUES LESS THAN (2011),

  10. PARTITION p_2012 VALUES LESS THAN (2012),

  11. PARTITION p_catchall VALUES LESS THAN MAXVALUE);

 

分表的適用場景

  • 一張表的查詢速度已經慢到影響使用的時候。
  • 當頻繁插入或者聯合查詢時,速度變慢。
  • 分表的實現需要業務結合實現和遷移,較為複雜。

 

 

四、分表和分庫

分表能夠解決單表資料量過大帶來的查詢效率下降的問題,但是,卻無法給資料庫的併發處理能力帶來質的提升

面對高併發的讀寫訪問,當資料庫master伺服器無法承載寫操作壓力時,不管如何擴充套件slave伺服器,此時都沒有意義了。因此,我們必須換一種思路,對資料庫進行拆分,從而提高資料庫寫入能力,這就是所謂的分庫。

與分表策略相似,分庫可以採用通過一個關鍵字取模的方式,來對資料訪問進行路由,如下圖所示

 

五、分庫分表存在的問題

1 事務問題。

在執行分庫分表之後,由於資料儲存到了不同的庫上,資料庫事務管理出現了困難。如果依賴資料庫本身的分散式事務管理功能去執行事務,將付出高昂的效能代價;如果由應用程式去協助控制,形成程式邏輯上的事務,又會造成程式設計方面的負擔。

2 跨庫跨表的join問題。

在執行了分庫分表之後,難以避免會將原本邏輯關聯性很強的資料劃分到不同的表、不同的庫上,這時,表的關聯操作將受到限制,我們無法join位於不同分庫的表,也無法join分表粒度不同的表,結果原本一次查詢能夠完成的業務,可能需要多次查詢才能完成。

3 額外的資料管理負擔和資料運算壓力。

額外的資料管理負擔,最顯而易見的就是資料的定位問題和資料的增刪改查的重複執行問題,這些都可以通過應用程式解決,但必然引起額外的邏輯運算,例如,對於一個記錄使用者成績的使用者資料表userTable,業務要求查出成績最好的100位,在進行分表之前,只需一個order by語句就可以搞定,但是在進行分表之後,將需要n個order by語句,分別查出每一個分表的前100名使用者資料,然後再對這些資料進行合併計算,才能得出結果。

解決方案

         使用類似JTA(JAVA TRANSACTION  API)提供的分散式事物機制

 

六、分片(Sharding)和分割槽(Partition)

sharding和partition的區別: