MySQL全面瓦解29:使用Partition功能實現水平分割槽

翁智華發表於2021-12-07

1 回顧

上一節我們詳細講解了如何對資料庫進行分割槽操作,包括了 垂直拆分(Scale Up 縱向擴充套件)和 水平拆分(Scale Out 橫向擴充套件) ,同時簡要整理了水平分割槽的幾種策略,現在來回顧一下。

2 水平分割槽的5種策略

2.1 Hash(雜湊) 

這種策略是通過對錶的一個或多個列的Hash Key進行計算,最後通過這個Hash碼不同數值對應的資料區域進行分割槽。例如我們可以建立一個對錶的日期的年份進行分割槽的策略,這樣每個年份都會被聚集在一個區間。

1 PARTITION BY HASH(YEAR(createtime))
2 PARTITIONS 10

2.2 Range(範圍) 

這種策略是將資料劃分不同範圍。例如我們可以將一個千萬級別的表通過id劃分成4個分割槽,每個分割槽大約500W的資料,超過750W後的資料統一放在第4個分割槽。 

1 PARTITION BY RANGE(id) (
2 PARTITIONP0 VALUES LESS THAN(2500001),
3 PARTITIONP1 VALUES LESS THAN(5000001),
4 PARTITIONp2 VALUES LESS THAN(7500001),
5 PARTITIONp3 VALUES LESS THAN MAXVALUE
6 )  

2.3 Key(鍵值) 

Hash策略的一種延伸,這裡的Hash Key是MySQL系統產生的。 

2.4、List(預定義列表) 

這種策略允許系統通過定義列表的值所對應的行資料進行分割。例如,我們根據崗位編碼進行分割槽,不同崗位型別的編碼對應到不同的分割槽去,達到分治的目的。

1 PARTITION BY LIST(gwcode) (
2 PARTITIONP0 VALUES IN (46,77,89),
3 PARTITIONP1 VALUES IN (106,125,177),
4 PARTITIONP2 VALUES IN (205,219,289),
5 PARTITIONP3 VALUES IN (302,317,458,509,610)
6

上述的SQL指令碼,使用了列表匹配LIST函式對員工崗位編號進行分割槽,共分為4個分割槽,行政崗位 編號為46,77,89的對應在分割槽P0中,技術崗位 106,125,177類別在分割槽P1中,依次類推即可。

2.5、Composite(複合模式) 

複合模式其實就是對上面幾種模式的組合使用,比如你在Range的基礎上,再進行Hash 雜湊分割槽。 

3 測試Range策略

3.1 建立總表與分表

我們建立一個普通的使用者表 users,再建立一個分割槽表users_part,將80年代出生的使用者按照年份進行了分割槽,如下:

3.1.1 總表語句
1 mysql> CREATE TABLE users
2 (
3  "id" int(10) unsigned NOT NULL,
4   "name" varchar(100) DEFAULT NULL,
5   "birth" datetime
6 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
7 Query OK, 0 rows affected 
3.1.2 分表語句
 1 mysql> create table users_part
 2 (
 3  "id" int(10) unsigned NOT NULL,
 4   "name" varchar(100) DEFAULT NULL,
 5   "birth" datetime
 6 ) ENGINE=InnoDB DEFAULT CHARSET=utf8
 7 PARTITION BY RANGE (year(birth)) (
 8 PARTITION p0 VALUES LESS THAN (1981),
 9 PARTITION p1 VALUES LESS THAN (1982),
10 PARTITION p2 VALUES LESS THAN (1983),
11 PARTITION p3 VALUES LESS THAN (1984),
12 PARTITION p4 VALUES LESS THAN (1985),
13 PARTITION p5 VALUES LESS THAN (1986),
14 PARTITION p6 VALUES LESS THAN (1987),
15 PARTITION p7 VALUES LESS THAN (1988),
16 PARTITION p8 VALUES LESS THAN (1989),17 PARTITION p9 VALUES LESS THAN MAXVALUE
18 );
19 Query OK, 0 rows affected

最後一行注意一下,是將89年之後出生的都歸屬到第10個分割槽上,我們這邊模擬的都是80年代出生的使用者,實際業務中跟據具體情況進行拆分。

3.2 初始化表資料

我們可以使用函式或者儲存過程批量進行資料初始化,這邊插入1000W條資料。

 1 DROP PROCEDURE IF EXISTS init_users_part;
 2 
 3 delimiter $     /* 設定語句終結符為 $*/
 4 CREATE PROCEDURE init_users_part()
 5   begin
 6    DECLARE srt int default 0;
 7    while 
 8     srt < 10000000  /* 設定寫入1000W的資料 */
 9    do
10     insert into `users_part` values (srt, concat('username_',idx1),adddate('1980-01-01',rand() * 3650)); /*在10年的時間內隨機取值*/
11     set srt = srt + 1;
12    end while;
13   end14 delimiter ;
15 
16 
17 call init_users_part(); 

3.3 同步資料至完整表中

1 mysql> insert into users select * from users_part;      //將1000w資料複製到未分割槽的完整表users 中
2 Query OK, 10000000 rows affected (51.59 sec) 
3 Records: 10000000 Duplicates: 0 Warnings: 0 

3.4 測試執行SQL的效率

 1 mysql> select count(*) from users_part where `birth`  > '1986-01-01' and `birth` < '1986-12-31';
 2 +----------+
 3 | count(*) |
 4 +----------+
 5 |   976324 |
 6 +----------+
 7 1 row in set (0.335 sec)
 8 
 9 mysql> select count(*) from users where `birth`  > '1986-01-01' and `birth` < '1986-12-31';
10 +----------+
11 | count(*) |
12 +----------+
13 |   976324 |
14 +----------+
15 1 row in set (5.187 sec) 

結果比較清晰,分割槽表的執行效率確實比較高,執行時間是未分割槽表 1/10 都不到。

3.5 使用Explain執行計劃分析

 1 mysql> explain select count(*) from users_part where `birth`  > '1986-01-01' and `birth` < '1986-12-31';
 2 +----+-------------+------------+------------+------+---------------+------+---------+------+-------+----------+-------------+
 3 | id | select_type | table      | partitions | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra       |
 4 +----+-------------+------------+------------+------+---------------+------+---------+------+-------+----------+-------------+
 5 |  1 | SIMPLE      | users_part | p7         | ALL  | NULL          | NULL | NULL    | NULL | 987769|   100.00 | Using where |
 6 +----+-------------+------------+------------+------+---------------+------+---------+------+-------+----------+-------------+
 7 1 row in set, 1 warning (0.00 sec)
 8 
 9 mysql> explain select count(*) from users where  `birth`  > '1986-01-01' and `birth` < '1986-12-31';
10 +----+-------------+-------+------------+------+---------------+------+---------+------+---------+----------+-------------+
11 | id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows    | filtered | Extra       |
12 +----+-------------+-------+------------+------+---------------+------+---------+------+---------+----------+-------------+
13 |  1 | SIMPLE      | users | NULL       | ALL  | NULL          | NULL | NULL    | NULL |10000000 |   100.00 | Using where |
14 +----+-------------+-------+------------+------+---------------+------+---------+------+---------+----------+-------------+
15 1 row in set, 1 warning (0.00 sec) 

這邊關注兩個關鍵引數:一個 是partitions,users_part中是p7,說明資料檢索在第七分割槽中,users表是null的,說明是全區域掃描,無分割槽。

另外一個引數是rows,是預測掃描的行數,users表明顯是全表掃描。

3.6 建索引提效

因為我們使用birth欄位進行分割槽和條件查詢,所以這邊嘗試在birth欄位上簡歷索引進行效率優化。

1 mysql> create index idx_user on users(birth);
2 Query OK, 0 rows affected (1 min 7.04 sec)
3 Records: 10000000  Duplicates: 0  Warnings: 0
4 
5 mysql> create index idx_user_part on users_part(birth);
6 Query OK, 0 rows affected (1 min 1.05 sec)
7 Records: 10000000  Duplicates: 0  Warnings: 0 

建立索引後的資料庫檔案大小列表:

2008-05-24 09:23             8,608 no_part_tab.frm
2008-05-24 09:24       255,999,996 no_part_tab.MYD
2008-05-24 09:24        81,611,776 no_part_tab.MYI
2008-05-24 09:25                 0 part_tab#P#p0.MYD
2008-05-24 09:26             1,024 part_tab#P#p0.MYI
2008-05-24 09:26        25,550,656 part_tab#P#p1.MYD
2008-05-24 09:26         8,148,992 part_tab#P#p1.MYI
2008-05-24 09:26        25,620,192 part_tab#P#p10.MYD
2008-05-24 09:26         8,170,496 part_tab#P#p10.MYI
2008-05-24 09:25                 0 part_tab#P#p11.MYD
2008-05-24 09:26             1,024 part_tab#P#p11.MYI
2008-05-24 09:26        25,656,512 part_tab#P#p2.MYD
2008-05-24 09:26         8,181,760 part_tab#P#p2.MYI
2008-05-24 09:26        25,586,880 part_tab#P#p3.MYD
2008-05-24 09:26         8,160,256 part_tab#P#p3.MYI
2008-05-24 09:26        25,585,696 part_tab#P#p4.MYD
2008-05-24 09:26         8,159,232 part_tab#P#p4.MYI
2008-05-24 09:26        25,585,216 part_tab#P#p5.MYD
2008-05-24 09:26         8,159,232 part_tab#P#p5.MYI
2008-05-24 09:26        25,655,740 part_tab#P#p6.MYD
2008-05-24 09:26         8,181,760 part_tab#P#p6.MYI
2008-05-24 09:26        25,586,528 part_tab#P#p7.MYD
2008-05-24 09:26         8,160,256 part_tab#P#p7.MYI
2008-05-24 09:26        25,586,752 part_tab#P#p8.MYD
2008-05-24 09:26         8,160,256 part_tab#P#p8.MYI
2008-05-24 09:26        25,585,824 part_tab#P#p9.MYD
2008-05-24 09:26         8,159,232 part_tab#P#p9.MYI
2008-05-24 09:25             8,608 part_tab.frm
2008-05-24 09:25                68 part_tab.par

再次測試SQL效能

 1 mysql> select count(*) from users_part where `birth`  > '1986-01-01' and `birth` < '1986-12-31';
 2 +----------+
 3 | count(*) |
 4 +----------+
 5 |   976324 |
 6 +----------+
 7 1 row in set (0.171 sec)
 8 
 9 mysql> select count(*) from users where `birth`  > '1986-01-01' and `birth` < '1986-12-31';
10 +----------+
11 | count(*) |
12 +----------+
13 |   976324 |
14 +----------+
15 1 row in set (0.583 sec) 

這邊可以看到,在關鍵的欄位新增索引並重啟(net stop mysql,net start mysql)之後,分割槽的表效能有略微提升。而未分割槽的全表效能提升最明顯,幾乎接近分割槽的效率。

3.7 跨區執行效率分析

通過上面的分析可以看出,在單個區內執行,比不分割槽效率又很明顯的差距,這是因為分割槽之後掃描非範圍縮小了。

那如果我們上面條件增加出生年份的範圍,讓他產生跨區域的情況,效果會怎麼樣呢,我們測試一下。

 1 mysql> select count(*) from users_part where `birth`  > '1986-01-01' and `birth` < '1987-12-31';
 2 +----------+
 3 | count(*) |
 4 +----------+
 5 |   976324 |
 6 +----------+
 7 1 row in set (1.914 sec)
 8 
 9 mysql> select count(*) from users where `birth`  > '1986-01-01' and `birth` < '1987-12-31';
10 +----------+
11 | count(*) |
12 +----------+
13 |   976324 |
14 +----------+
15 1 row in set (3.871 sec) 

可見,跨區之後效能會差一些。這邊應該這樣理解,跨區的越多,效能越差,所以做分割槽設計的時候應該意識到,避免那種頻繁的跨區情況發生,謹慎判斷分割槽邊界條件。   

3.8 總結

1、分割槽和未分割槽佔用檔案空間大致相同 (資料和索引檔案)

2、查詢語句中關鍵欄位未建立索引欄位時,分割槽時間遠遠優於未分割槽時間

3、如果查詢語句中欄位建立了索引,分割槽和未分割槽的差別縮小,但是仍然優於未分割槽情況,而且隨著資料量增加,這個優勢會更明顯。

4、對於大資料量,還是建議使用分割槽功能,無論他有沒有建立索引。

5、根據MySQL手冊, 增加myisam_max_sort_file_size 會增加分割槽效能( mysql重建索引時允許使用的臨時檔案最大大小)

6、對分割槽進行設計時,謹慎判斷分割槽邊界條件,避免有過度頻繁的跨區操作,否則效能不會理想。 

4 分割槽策略詳解

4.1 HASH(雜湊)

HASH分割槽主要用來確保資料在預先確定數目的分割槽中平均分佈,而在RANGE和LIST分割槽中,必須明確指定一個給定的列值或列值集合應該儲存在哪個分割槽中,

而在HASH分割槽中,MySQL自動完成這些工作,

你所要做的只是基於將要被雜湊的列值指定一個列值或表示式,以及指定被分割槽的表將要被分割成的分割槽數量。 示例如下:

 1 /*Hash*/
 2 drop table if EXISTS  `t_userinfo`; 
 3 CREATE TABLE `t_userinfo` (
 4 `id` int(10) unsigned NOT NULL,
 5 `personcode` varchar(20) DEFAULT NULL,
 6 `personname` varchar(100) DEFAULT NULL,
 7 `depcode` varchar(100) DEFAULT NULL,
 8 `depname` varchar(500) DEFAULT NULL,
 9 `gwcode` int(11) DEFAULT NULL,
10 `gwname` varchar(200) DEFAULT NULL,
11 `gravalue` varchar(20) DEFAULT NULL,
12 `createtime` DateTime NOT NULL
13 ) ENGINE=InnoDB DEFAULT CHARSET=utf8
14 PARTITION BY HASH(YEAR(createtime))
15 PARTITIONS 4(
16      PARTITION P0 DATA DIRECTORY = '/data0/data' INDEX DIRECTORY = '/data0/idx', 
17      PARTITION P1 DATA DIRECTORY = '/data1/data' INDEX DIRECTORY = '/data1/idx', 
18      PARTITION P2 DATA DIRECTORY = '/data2/data' INDEX DIRECTORY = '/data2/idx', 
19      PARTITION P3 DATA DIRECTORY = '/data3/data' INDEX DIRECTORY = '/data3/idx'
20 );

上面的例子,使用HASH函式對createtime日期進行HASH運算,並根據這個日期來分割槽資料,這裡共分為10個分割槽。 

建表語句上新增一個“PARTITION BY HASH (expr)”子句,其中“expr”是一個返回整數的表示式,它可以是欄位型別為MySQL 整型的一列的名字,也可以是返回非負數的表示式。

另外,可能需要在後面再新增一個“PARTITIONS num”子句,其中num 是一個非負的整數,它表示表將要被分割成分割槽的數量。 

每個分割槽都有自己獨立的資料、索引檔案的存放目錄,並且這些目錄所在的物理磁碟分割槽可能也都是完全獨立的,可以提高磁碟IO吞吐量。 

4.2 RANGE(範圍)

基於屬於一個給定連續區間的列值,把多行分配給同一個分割槽,這些區間要連續且不能相互重疊,使用VALUES LESS THAN操作符來進行定義。示例如下:

 1 /*Range*/
 2 drop table if EXISTS  `t_userinfo`; 
 3 CREATE TABLE `t_userinfo` (
 4 `id` int(10) unsigned NOT NULL,
 5 `personcode` varchar(20) DEFAULT NULL,
 6 `personname` varchar(100) DEFAULT NULL,
 7 `depcode` varchar(100) DEFAULT NULL,
 8 `depname` varchar(500) DEFAULT NULL,
 9 `gwcode` int(11) DEFAULT NULL,
10 `gwname` varchar(200) DEFAULT NULL,
11 `gravalue` varchar(20) DEFAULT NULL,
12 `createtime` DateTime NOT NULL
13 ) ENGINE=InnoDB DEFAULT CHARSET=utf8
14 PARTITION BY RANGE(gwcode) (
15 PARTITION P0 VALUES LESS THAN(101) DIRECTORY = '/data0/data' INDEX DIRECTORY = '/data0/idx',
16 PARTITION P1 VALUES LESS THAN(201) DIRECTORY = '/data1/data' INDEX DIRECTORY = '/data1/idx',
17 PARTITION P2 VALUES LESS THAN(301) DIRECTORY = '/data2/data' INDEX DIRECTORY = '/data2/idx',
18 PARTITION P3 VALUES LESS THAN MAXVALUE DIRECTORY = '/data3/data' INDEX DIRECTORY = '/data3/idx'
19 );

上面的示例,使用了範圍RANGE函式對崗位編號進行分割槽,共分為4個分割槽,

崗位編號為1~100 的對應在分割槽P0中,101~200的編號在分割槽P1中,依次類推即可。那麼類別編號大於300,可以使用MAXVALUE來將大於300的資料統一存放在分割槽P3中即可。 

每個分割槽都有自己獨立的資料、索引檔案的存放目錄,並且這些目錄所在的物理磁碟分割槽可能也都是完全獨立的,可以提高磁碟IO吞吐量。 

4.3 LIST(預定義列表)

類似於按RANGE分割槽,區別在於LIST分割槽是基於列值匹配一個離散值集合中的某個值來進行選擇分割槽的。LIST分割槽通過使用“PARTITION BY LIST(expr)”來實現,其中“expr” 是某列值或一個基於某個列值、並返回一個整數值的表示式,

然後通過“VALUES IN (value_list)”的方式來定義每個分割槽,其中“value_list”是一個通過逗號分隔的整數列表。 示例如下:

 1 /*List*/
 2 drop table if EXISTS  `t_userinfo`; 
 3 CREATE TABLE `t_userinfo` (
 4 `id` int(10) unsigned NOT NULL,
 5 `personcode` varchar(20) DEFAULT NULL,
 6 `personname` varchar(100) DEFAULT NULL,
 7 `depcode` varchar(100) DEFAULT NULL,
 8 `depname` varchar(500) DEFAULT NULL,
 9 `gwcode` int(11) DEFAULT NULL,
10 `gwname` varchar(200) DEFAULT NULL,
11 `gravalue` varchar(20) DEFAULT NULL,
12 `createtime` DateTime NOT NULL
13 ) ENGINE=InnoDB DEFAULT CHARSET=utf8
14 PARTITION BY LIST(`gwcode`) (
15 PARTITION P0 VALUES IN (46,77,89) DATA DIRECTORY = '/data0/data' INDEX DIRECTORY = '/data0/idx',
16 PARTITION P1 VALUES IN (106,125,177) DATA DIRECTORY = '/data1/data' INDEX DIRECTORY = '/data1/idx',
17 PARTITION P2 VALUES IN (205,219,289) DATA DIRECTORY = '/data2/data' INDEX DIRECTORY = '/data2/idx',
18 PARTITION P3 VALUES IN (302,317,458,509,610) DATA DIRECTORY = '/data3/data' INDEX DIRECTORY = '/data3/idx'
19 );

上面的例子,使用了列表匹配LIST函式對員工崗位編號進行分割槽,共分為4個分割槽,編號為46,77,89的對應在分割槽P0中,106,125,177類別在分割槽P1中,依次類推即可。

不同於RANGE的是,LIST分割槽的資料必須匹配列表中的崗位編號才能進行分割槽,所以這種方式只是適合比較區間值確定並少量的情況。 

每個分割槽都有自己獨立的資料、索引檔案的存放目錄,並且這些目錄所在的物理磁碟分割槽可能也都是完全獨立的,可以提高磁碟IO吞吐量。 

4.4 KEY(鍵值)

類似於按HASH分割槽,區別在於KEY分割槽只支援計算一列或多列,且MySQL 伺服器提供其自身的雜湊函式。必須有一列或多列包含整數值。 示例如下:

 1 /*key*/
 2 drop table if EXISTS  `t_userinfo`; 
 3 CREATE TABLE `t_userinfo` (
 4 `id` int(10) unsigned NOT NULL,
 5 `personcode` varchar(20) DEFAULT NULL,
 6 `personname` varchar(100) DEFAULT NULL,
 7 `depcode` varchar(100) DEFAULT NULL,
 8 `depname` varchar(500) DEFAULT NULL,
 9 `gwcode` int(11) DEFAULT NULL,
10 `gwname` varchar(200) DEFAULT NULL,
11 `gravalue` varchar(20) DEFAULT NULL,
12 `createtime` DateTime NOT NULL
13 ) ENGINE=InnoDB DEFAULT CHARSET=utf8
14 PARTITION BY KEY(gwcode)
15 PARTITIONS 4(
16      PARTITION P0 DATA DIRECTORY = '/data0/data' INDEX DIRECTORY = '/data0/idx', 
17      PARTITION P1 DATA DIRECTORY = '/data1/data' INDEX DIRECTORY = '/data1/idx', 
18      PARTITION P2 DATA DIRECTORY = '/data2/data' INDEX DIRECTORY = '/data2/idx', 
19      PARTITION P3 DATA DIRECTORY = '/data3/data' INDEX DIRECTORY = '/data3/idx'
20 );

注意:此種分割槽演算法目前使用的比較少,使用伺服器提供的雜湊函式有不確定性,對於後期資料統計、整理存在會更復雜,所以我們更傾向於使用由我們定義表示式的Hash,大家知道其存在和怎麼使用即可。 

4.5 巢狀分割槽(子分割槽)

巢狀分割槽(子分割槽)是針對 RANGE/LIST 型別的分割槽表中每個分割槽的再次分割。再次分割可以是 HASH/KEY 等型別。

 1 drop table if EXISTS `t_userinfo`;
 2 CREATE TABLE `t_userinfo` (
 3 `id` int(10) unsigned NOT NULL,
 4 `personcode` varchar(20) DEFAULT NULL,
 5 `personname` varchar(100) DEFAULT NULL,
 6 `depcode` varchar(100) DEFAULT NULL,
 7 `depname` varchar(500) DEFAULT NULL,
 8 `gwcode` int(11) DEFAULT NULL,
 9 `gwname` varchar(200) DEFAULT NULL,
10 `gravalue` varchar(20) DEFAULT NULL,
11 `createtime` DateTime NOT NULL
12 ) ENGINE=InnoDB DEFAULT CHARSET=utf8
13 PARTITION BY RANGE (id) SUBPARTITION BY HASH (id% 4) SUBPARTITIONS 2(
14      PARTITION p0 VALUES LESS THAN (5000000) DATA DIRECTORY = '/data0/data' INDEX DIRECTORY = '/data0/idx', 
15      PARTITION p1 VALUES LESS THAN MAXVALUE DATA DIRECTORY = '/data1/data' INDEX DIRECTORY = '/data1/idx'
16 
17 ); 

 如上,對RANGE 分割槽再次進行子分割槽劃分,子分割槽採用 HASH 型別。   

5 分割槽管理

5.1 刪除分割槽  

1  /*刪除分割槽 P1*/
2  ALERT TABLE users_part DROP PARTITION P1; 

5.2 重建分割槽

5.2.1 RANGE 分割槽重建
1 /*這邊將原來的 P0,P1 分割槽合併起來,放到新的 P0 分割槽中,並重新設定條件為少於5000000。*/
2 ALTER TABLE users_part REORGANIZE PARTITION P0,P1 INTO (PARTITION P0 VALUES LESS THAN (5000000));   

用於因空間過於浪費而產生的合併情況。

5.2.2 LIST 分割槽重建
/*將原來的 P0,P1 分割槽合併起來,放到新的 P0 分割槽中,跟上一個的意思有點像。*/
ALTER TABLE users_part REORGANIZE PARTITION p0,p1 INTO (PARTITION p0 VALUES IN(1,4,5,8,9,12,13,101,555)); 
5.2.3 HASH/KEY 分割槽重建
/*用 REORGANIZE 方式重建分割槽的數量變成2,在這裡數量只能減少不能增加。想要增加可以用 ADD PARTITION 方法。*/
ALTER TABLE users_part REORGANIZE PARTITION COALESCE PARTITION 2; 

5.3 新增分割槽

5.3.1 新增 RANGE 分割槽   
1 /*新增一個RANGE分割槽*/
2 ALTER TABLE category ADD PARTITION (PARTITION p4 VALUES IN (16,17,18,19) 
3 DATA DIRECTORY = '/data8/data'
4 INDEX DIRECTORY = '/data8/idx');
5.3.2 新增 HASH/KEY 分割槽
/* 將分割槽總數擴充套件到n個。n請用數值代替 */
ALTER TABLE users_part ADD PARTITION PARTITIONS n; 
5.3.3 給已有的表加上分割槽
 1 alter tableuser_part partition by RANGE (month(birth)) 
 2 (
 3 PARTITION p0 VALUES LESS THAN (1),
 4 PARTITION p1 VALUES LESS THAN (2) , 
 5 PARTITION p2 VALUES LESS THAN (3) ,
 6 PARTITION p3 VALUES LESS THAN (4) , 
 7 PARTITION p4 VALUES LESS THAN (5) ,
 8 PARTITION p5 VALUES LESS THAN (6) , 
 9 PARTITION p6 VALUES LESS THAN (7) ,
10 PARTITION p7 VALUES LESS THAN (8) , 
11 PARTITION p8 VALUES LESS THAN (9) ,
12 PARTITION p9 VALUES LESS THAN (10) , 
13 PARTITION p10 VALUES LESS THAN (11),
14 PARTITION p11 VALUES LESS THAN (12),
15 PARTITION P12 VALUES LESS THAN (13) 
16 );

6 去除分割槽主鍵限制

預設分割槽限制分割槽欄位必須是主鍵(PRIMARY KEY)的一部分,需要去除此限制。

如果表中設立主鍵,會報出如下提示:A PRIMARY KEY must include all columns in the table's partitioning function (prefixed columns are not considered).

一種解決方式就是使用主鍵來做為分割槽條件:

ALTER TABLE users_part  PARTITION BY HASH(id)  PARTITIONS 4;  

另外一種方式就是把分割槽條件欄位加入主鍵中,變成聯合主鍵。如下,id和gwcode 組成了聯合主鍵:

1 alter table users_part drop PRIMARY KEY;
2 alter table users_part add PRIMARY KEY(id, gwcode); 

相關文章