mysql 分庫分表分區總結

Mysql目錄結構

一個庫一個目錄

 

MyISAM引擎

 

InnoDB引擎

 

分庫分表分區總結

對於分區分表 都可以進行橫向(按表字段分),縱向分(按數據行分),此文暫時值考慮橫向分。

對於分庫:分庫

分區

說明

分區和分表類似,把原本的一個數據量很大的表,根據規則分成很多塊。這些塊可以跨磁盤分佈。突破單磁盤IO的限制。

好處

  1. 分區爲了突破IO瓶頸,可以把索引及數據文件放在不同磁盤。
  2. 可以根據自定義的分區方式 優化查詢,比如根據分區列查詢,就會定位到某個分區只查某分區的數據。
  3. 完全在數據庫層面操作,與代碼解耦,不需要java代碼等進行邏輯處理,後期增加,拆分,合併,刪除 方便。
  4. 不用關心跨分區統計查詢問題,數據庫層面已經處理好。

缺點

  1. 要事先預估數據量,後期可能會隨着數據的增加而需要重新映射分區。
  2. 只能在一個數據庫實例中,內存加載和計算只能在一臺機器中。

分表

說明

分表是建立多張子表,每張表的表字段相同,根據映射算法把數據分到不同子表。數據文件只能在一個磁盤上,一個數據庫實例中。

 

好處

  1. 可以根據自定義的表字段映射算法,把每次增刪改查時的操作映射到的表,這樣可以少查詢數據。可以數據量很大的表表 橫向拆分爲多個子表。

缺點

  1. 需要java代碼邏輯處理映射算法。比較複雜。

(2)只能在一個數據庫實例中,只能在一個磁盤中,內存加載和計算只能在一臺機器中。

(3)要事先預估數據量,後期可能會隨着數據的擴容重新擴展映射表。

(4)對於跨子表的統計查詢,會比較複雜。

分庫

 

 

好處

分庫 可以突破服務器單節點內存,和計算的的限制。具體可以通自定義程序邏輯實現。根據場景自己實現即可。

如:主從備份讀寫分離,數據庫按業務進行分(縱向)。把一張很大的表橫向切分 並放在不同的庫中(映射方法類似於分表分區)。

缺點

分庫要考慮跨庫多表查詢的問題。

要考慮分佈式事務的問題。

 

分區

主要可以利用多個磁盤,提高IO性能。

分區把一個表數據和索引存儲到多個不同的地方,跨磁盤,(可以跨文件系統,前提是當前系統可以看到此文件系統),可以指定每個分區文件存儲的位置。

分區可以分爲垂直分區(對一個大表,拆字段分別放在不同分區),和水平分區(把特定的某些行分開存放)。目前mysql只支持水平分區。

指定分區所在磁盤的文件:https://blog.csdn.net/xuheng8600/article/details/79817040

分區具體命令操作:https://blog.csdn.net/qq_35726305/article/details/81221721

分區可以調整(如把一個分區調整爲2個),可以合併(如把兩個分區合併爲一個),可以追加,可以刪除

在做分區前,也要先預估數據量,然後分爲幾個區。最好是按照時間分區,比如一年一個分區,這樣就不用預估多少個分區,每一年開始就追加一個分區即可

Mysql分區類型

根據所使用的不同分區規則可以分成幾大分區類型。

 

RANGE 分區:

 

基於屬於一個給定連續區間的列值,把多行分配給分區。

 

LIST 分區:

 

類似於按RANGE分區,區別在於LIST分區是基於列值匹配一個離散值集合中的某個值來進行選擇。

 

HASH分區:

 

基於用戶定義的表達式的返回值來進行選擇的分區,該表達式使用將要插入到表中的這些行的列值進行計算。這個函數可以包含MySQL中有效的、產生非負整數值的任何表達式。

 

KEY

分區:類似於按HASH分區,區別在於KEY分區只支持計算一列或多列,且MySQL服務器提供其自身的哈希函數。必須有一列或多列包含整數值。

 

複合分區:

 

基於RANGE/LIST 類型的分區表中每個分區的再次分割。子分區可以是 HASH/KEY 等類型。

 

對錶做range分區

create table t5 (a varchar(20) not null,b varchar(11) not null,id int not null) partition by range(id)

(

partition s1 values less than(2000000),

partition s2 values less than(4000000),

partition s3 values less than(10000000)

)

可見分爲三個區後,在mysql的數據庫目錄下,多了三個ibd分區的文件,和一個frm的表信息文件。

 

不使用分區列查詢,可以看到用到了三個分區

 

分區約束

  1. 在5.1版本中分區表對唯一約束有明確的規定,每一個唯一約束必須包含在分區表的分區鍵(也包括主鍵約束)。
  2. 還有很多約束,比如不能外鍵,以及innordb,MyISAM引擎上的約束等等。

分區後查詢性能

注意此處測試時,我所有分區都在一個磁盤,所以不考慮多個磁盤會提升IO性能的問題。

 

test1是沒有分區的表,t5是分爲三個區的表(按照id:<2000000,<4000000,<10000000)。兩個表都沒有索引,數據都一樣,總量都爲6291456條。

兩個 表格式如下

 

條件不包含分區列

可以看到,條件如果沒有分區列,則會查詢三個分區。速度上兩者差不多。

 

 

 

 

條件包含分區列

在一個分區內的數據查詢

可以看到只使用一個分區。速度要比不分區要快的多。

 

 

數據跨兩個分區

可以看到id<2500000的數據跨了兩個分區。同樣比不分區要快。

 

 

 

跨所有分區

當條件id<4500000時跨所有三個分區,速度上兩者差不多。

 

 

 

分表

分表有多種方式,目前我們只說兩種。做分表前,最好要提前預估數據量(不然後面要增加子表需要重建映射關係),並根據數據量 確定使用的映射子表的算法。最好能夠按年進行分表,這樣就能很好的解決建多少張表的問題。

另外可以考慮一致性hash。

Merge引擎實現表合併(不推薦)

主要原理是利用MERGE引擎創建一個主表,把兩張子表關聯起來(方便總的統計查詢)。這樣只查詢主表即可。但是由於主表插入的函數只有兩個選項LAST或者FIRST(即插入到最後一個子表或者第一個子表)。因此需要自己再程序中創建映射子表的算法。

Sql語句

  1. 創建兩張子表(必須使用MyISAM引擎),並添加數據

 

  1. mysql> CREATE TABLE IF NOT EXISTS `user1` (  
  2.  ->   `id` int(11) NOT NULL AUTO_INCREMENT,  
  3.  ->   `name` varchar(50) DEFAULT NULL,  
  4.  ->   `sex` int(1) NOT NULL DEFAULT '0',  
  5.  ->   PRIMARY KEY (`id`)  
  6.  -> ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;  
  7. Query OK, 0 rows affected (0.05 sec)  
  8.   
  9. mysql> CREATE TABLE IF NOT EXISTS `user2` (  
  10.  ->   `id` int(11) NOT NULL AUTO_INCREMENT,  
  11.  ->   `name` varchar(50) DEFAULT NULL,  
  12.  ->   `sex` int(1) NOT NULL DEFAULT '0',  
  13.  ->   PRIMARY KEY (`id`)  
  14.  -> ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;  
  15. Query OK, 0 rows affected (0.01 sec)  
  16.   
  17. mysql> INSERT INTO `user1` (`name`, `sex`) VALUES('張映', 0);  
  18. Query OK, 1 row affected (0.00 sec)  
  19.   
  20. mysql> INSERT INTO `user2` (`name`, `sex`) VALUES('tank', 1);  
  21. Query OK, 1 row affected (0.00 sec)

 

 

  1. 創建主表(必須使用MRG_MYISAM引擎)
  1. ysql> CREATE TABLE IF NOT EXISTS `alluser` (  
  2.  ->   `id` int(11) NOT NULL AUTO_INCREMENT,  
  3.  ->   `name` varchar(50) DEFAULT NULL,  
  4.  ->   `sex` int(1) NOT NULL DEFAULT '0',  
  5.  ->   INDEX(id)  
  6.  -> ) TYPE=MERGE UNION=(user1,user2) INSERT_METHOD=NO AUTO_INCREMENT=1 ;  
  7. Query OK, 0 rows affected, 1 warning (0.00 sec)    

 

上述sql 中TYPE=MERGE表示使用MERGE存儲引擎; UNION=(user1,user2) 表示要把兩張表組合一起,INSERT_METHOD=NO 表示不允許插入主表。使用first或last值使得插入被相應地做在第一或最後一個表上。如果你沒有指定insert_method選項,或你用一個no值指定該選,則表示不允許插入主表。

 

總結

a1,a2,a3爲子表,a爲主表。數據文件如下

 

基於MERGE創建的分表,子表必須是myisam, 主表必須是mrg_myisam。此分表只有一個作用,就是利用MERGE合併表的方式,能夠統計所有分表的信息(其實完全可以使用sql語句union all)。完全不建議使用。

 

完全基於自定義映射算法

通過預估數據量,指定數據映射算法,對每次增刪改查操作映射到不同的子表上,減少查詢數據量。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章