LIST分區和RANGE分區非常的相似,主要區別在於LIST是枚舉值列表的集合,RANGE是連續的區間值的集合。二者在文法方面非常的相似。同樣建議LIST分區列是非null列,否則插入null值如果枚舉列表裡面不存在null值會插入失敗,這點和其它的分區不一樣,RANGE分區會將其作為最小分區值存儲,HASHKEY分為會將其轉換成0存儲,主要LIST分區只支援整形,非整形字段需要透過函數轉換成整形;5.5版本之後可以不需要函數轉換使用LIST COLUMN分區支援非整形字段,在COLUMN分區中有詳細的講解。
一、建立分區
List各個分區枚舉的值只需要不相同即可,沒有固定的順序。
CREATE TABLE tblist ( id INT NOT NULL, store_id INT ) PARTITION BY LIST(store_id) ( PARTITION a VALUES IN (1,5,6), PARTITION b VALUES IN (2,7,8), PARTITION c VALUES IN (3,9,10), PARTITION d VALUES IN (4,11,12) );
SELECT PARTITION_NAME,PARTITION_METHOD,PARTITION_EXPRESSION,PARTITION_DESCRIPTION,TABLE_ROWS,SUBPARTITION_NAME,SUBPARTITION_METHOD,SUBPARTITION_EXPRESSION FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA=SCHEMA() AND TABLE_NAME='tblist';
1.插入資料
insert into tblist(id,store_id) values(1,1),(7,7);
往a、b兩個分區中各插入一條記錄
2.插入不在列表中的值
2.插入不在列表中的值。枚舉列表中的值是會插入失敗,插入null值如果null值不在枚舉列表中也同樣失敗
二、分區管理
1.增加分區
ALTER TABLE tblist ADD PARTITION (PARTITION e VALUES IN (20));
注意:不能增加包含現有任意值的分區。
2.合併分區
ALTER TABLE tblist REORGANIZE PARTITION a,b INTO (PARTITION m VALUES IN (1,5,6,2,7,8));
將分區a,b合併為分區m
注意:同RANGE分區一樣,只能合併相鄰的幾個分區,不能跨分區合併。例如不能合併a,c兩個分區,只能透過合併a,b,c
3.拆分分區
ALTER TABLE tblist REORGANIZE PARTITION a,b,c INTO (PARTITION n VALUES IN (1,5,6,3,9,10), PARTITION m VALUES IN (2,7,8)); ALTER TABLE tblist REORGANIZE PARTITION n INTO ( PARTITION a VALUES IN (1,5,6), PARTITION b VALUES IN (3,9,10));
經過兩輪的拆分,枚舉列表(3,9, 10)排到了(2,7,8)的前面去了;其實是這樣的,一開始合併abc成nm兩個分區由於n中的枚舉值小於m所以n在m的前面,後面再拆分n分區由於n分區在m分區的前面所以拆分出來的分區也是排在m分區的前面,由於a分區的值小於b分區的值所以a排在b的前面。
注意:1.在5.7.12版本中測試發現,合併和拆分分區重新定義的枚舉值可以不是原來的值,如果原來的枚舉值包含了數據而新合併或拆分的分區枚舉值又不包含原來的枚舉值會造成資料遺失。雖然不知道為什麼mysql不會禁止該行為,但是人為的要求無論是合併還是拆分分區枚舉值保持不變,或者只能增加不能減少,這樣能保證資料不丟失。
2.合併和拆分後的分區由於是相鄰的分區進行合併和拆分會根據原本的分區的值新的分區也會在原本的分區的順序位置。
4.刪除分割區
ALTER TABLE tblist DROP PARTITION e;
注意:刪除分割區同時會將分割區中的資料刪除,同時列舉的list值也被刪除,後面無法往表中插入該值的資料。
三、其它分區
對時間字段進行分區
CREATE TABLE listdate ( id INT NOT NULL, hired DATETIME NOT NULL ) PARTITION BY LIST( YEAR(hired) ) ( PARTITION a VALUES IN (1990), PARTITION b VALUES IN (1991), PARTITION c VALUES IN (1992), PARTITION d VALUES IN (1993) ); ALTER TABLE listdate ADD INDEX ix_hired(hired); INSERT INTO listdate() VALUES(1,'1990-01-01 10:00:00'),(1,'1991-01-01 10:00:00'),(1,'1992-01-01 10:00:00');
EXPLAIN SELECT * FROM listdate WHERE hired='1990-01-01 10:00:00';
LIST分區也支援對非整形分區類型的轉換分區。
四、移除表的分區
ALTER TABLE tablename REMOVE PARTITIONING ;
注意:使用remove移除分區是僅移除分區的定義,並不會刪除資料和drop PARTITION不一樣,後者會連同資料一起刪除