1. 程式人生 > >MySQL的分表與分區

MySQL的分表與分區

創建 alter 讀寫 created 例如 mysq 不能 eth art

MySQL分表分區是解決大數據量導致MySQL性能低下的兩種方法。

什麽是MySQL分表

從表面意思上看,MySQL分表就是將一個表分成多個表,數據和數據結構都有可能會變。MySQL分表分為垂直分表和水平分表。

1、垂直分表

垂直分表是按表中的字段來劃分的,如下圖所示。

技術分享圖片

在上圖中,我們將本來分布在同一張表中的C1、C2、C3、C4四個字段垂直劃分到兩個表中。第一張表中分布C1、C3、C4三個字段,第二張表中分布C1、C2兩個字段。拆分後的兩個表通過C1這個共同的字段關聯起來。

2、水平分表

水平分表是按表中的記錄來劃分的。如下圖所示。

技術分享圖片

在上圖中,我們將本來分布在同一張表中的四條記錄,水平拆分到兩個表中。第一張表中,分布兩條記錄;第二張表中,分布兩條記錄。

3、分表操作

MySQL分表既可以自定義規則,也可以使用業內通用規則,還可以使用merge存儲引擎來實現。

1)自定義規則

按照用戶或業務的編號分表。對與用戶或業務可以按照編號%n,進行分成n表。

按照日期分表。對於日誌或統計類等的表。可以按照年,月,日,周分表。

2)使用Merge存儲引擎

使用Merge存儲引擎實現MySQL分表比較適合那些沒有事先考慮分表,隨著數據的增多,已經出現了數據查詢慢的情況。使用Merge存儲引擎實現MySQL分表可以避免改代碼。使用Merge實現MySQL分表可以按如下形式操作:

技術分享圖片

在上圖中,ENGINE = MERGE表示,使用merge引擎。另外ENGINE = MRG_MyISAM是一樣的意思。UNION = (user1, user2)表示,掛接了user1、user2表,INSERT_METHOD = LAST表示插入方式:0不允許插入,FIRST插入到UNION中的第一個表,LAST插入到UNION中的最後一個表。

使用Merge存儲引擎實現MySQL分表,分表後的結果會分為主表和子表,主表類似於一個殼子,邏輯上封裝了子表,實際上數據都是存儲在子表中的。如下圖所示。

技術分享圖片

上圖是對user表進行merge分表的結果,alluser是總表,user1和user2是分表。每一個表都有自己的表結構,子表而且還保存了數據和索引,總表沒有保存數據和索引,總表只保存了分表的關系,以及插入數據的方式。

4、分表查詢

對於分表後的查詢操作,依然是聯合查詢,視圖等基本操作,或者使用merge引擎合並數據並在此表中查詢。復雜一些操作需要借助存儲過程來完成,借助外部工具實現對分表的管理。如:

  • 垂直分表的使用join連接、水平分表的使用union連接。

  • 對於使用Merge存儲引擎實現的MySQL分表,可以直接查詢總表。

5、註意事項

1)重復記錄 / 重復索引

若建立Merge表前,分表t1 / t2已經存在,並且t1 / t2中存在重復記錄。查詢時,遇到滿足記錄的條目就會返回。意思就是只會顯示一條記錄,同時不會報錯。若建立Merge表後,insert / update時,出現重復索引,則會提示錯誤。MERGE表只對建表之後的操作負責。

2)如何刪除一個分表

不能直接刪除一個分表,這樣會破壞Merge表。正確的方法是:

alter table t ENGINE = MRG_MyISAM UNION = (t1) INSERT_METHOD = LAST;

drop table t1;

3)誤刪Merge總表

誤刪Merge表,是不會造成數據丟失的,只需重新創建總表。

什麽是MySQL分區

從表面意思看,MySQL分區就是將一張表的數據分成多個存儲區塊,而數據結構不變。另外,這些存儲區塊既可以在同一個磁盤上,也可以在不同的磁盤上。如下圖所示。

技術分享圖片

上圖是對表aa進行分區後,磁盤上的文件分布。從圖中我們可以看到,分區後aa表的數據結構沒有發生變化,而數據和索引存儲的位置由原來的一個變成了兩個。另外,多出了一個.par文件,打開.par文件後你可以看出他記錄了這張表的分區信息。

1、分區操作

MySQL從5.1.3開始支持Partition,你可以使用如下命令來確認你的版本是否支持Partition:

技術分享圖片

MySQL支持的分區類型包括Range、List、Hash、Key,其中Range比較常用:

1)Range(範圍) – 這種模式允許DBA將數據劃分不同範圍。例如DBA可以將一個表通過年份劃分成三個分區,80年代(1980‘s)的數據,90年代(1990‘s)的數據以及任何在2000年(包括2000年)後的數據。如下:

技術分享圖片

在這裏,將用戶表分成4個分區,以每300萬條記錄為界限,每個分區都有自己獨立的數據、索引文件的存放目錄。

2)List(預定義列表) – 這種模式允許系統通過DBA定義的列表的值所對應的行數據進行分割。例如:DBA根據用戶的類型進行分區。

技術分享圖片

3)Key(鍵值) – 上面Hash模式的一種延伸,這裏的Hash Key是MySQL系統產生的。

技術分享圖片

4)Hash(哈希) – 這中模式允許DBA通過對表的一個或多個列的Hash Key進行計算,最後通過這個Hash碼不同數值對應的數據區域進行分區,。例如DBA可以建立一個對表主鍵進行分區的表。

技術分享圖片

2、註意事項

1)以上每一種分區方式,都可以將這些分區所在的物理磁盤分開完全獨立,以提高磁盤IO吞吐量。如下:

技術分享圖片

上圖就是對Range(範圍)分區類型進行物理空間的分離操作。

2)分區雖然很爽,但目前的實現還有很多限制:

  • 主鍵或者唯一索引必須包含分區字段:如PRIMARY KEY(i,created)。

  • 很多時候,使用了分區就不要再使用主鍵,否則可能影響性能。

  • 只能通過int類型的字段或者返回int類型的表達式來分區:通常使用YEAR或TO_DAYS等函數。

  • 每個表最多1024個分區:不可能無限制的擴展分區,而且過度使用分區往往會消耗大量系統內存。

  • 采用分區的表不支持外鍵:相關的約束邏輯必須通過程序來實現。

MySQL分表和分區的異同

  1. 都能提高mysql的性高,在高並發狀態下都有一個良好的表現。

  2. 分表和分區不矛盾,可以相互配合的,對於那些大訪問量,並且表數據比較多的表,我們可以采取分表和分區結合的方式(如果merge這種分表方式,不能和分區配合的話,可以用其他的分表試),訪問量不大,但是表數據很多的表,我們可以采取分區的方式等。

  3. 分表技術是比較麻煩的,需要手動去創建子表,app服務端讀寫時候需要計算子表名。采用merge好一些,但也要創建子表和配置子表間的union關系。

  4. 表分區相對於分表,操作方便,不需要創建子表。

MySQL的分表與分區