Partition学习笔记
這幾天學習了一下分區,不經意間想起了三國演義開篇詞:“合久必分,分久必合”,看來這句話也適合數據庫,英文手冊和中文手冊對比,更新了很多東西,以后盡量看英文的了,下面是學習筆記:
理論部分:
1,基本概念:
分區可以設置任意大小的規則,跨文件系統分配單個表的多個部分。實際上,表的不同部分在不同的位置被存儲為單獨的表。用戶所選擇的、實現數據分割的規則被稱為分區函數,這在MySQL中它可以是模數,或者是簡單的匹配一個連續的數值區間或數值列表,或者是一個內部HASH函數,或一個線性HASH函數。函數根據用戶指定的分區類型來選擇,把用戶提供的表達式的值作為參數。該表達式可以是一個整數列值,或一個作用在一個或多個列值上并返回一個整數的函數。這個表達式的值傳遞給分區函數,分區函數返回一個表示那個特定記錄應該保存在哪個分區的序號。這個函數不能是常數,也不能是任意數。它不能包含任何查詢,但是實際上可以使用MySQL 中任何可用的SQL表達式,只要該表達式返回一個小于MAXVALUE(最大可能的正整數)的正數值。
?
?
2,注意事項:
對于創建了分區的表,可以使用你的MySQL 服務器所支持的任何存儲引擎;MySQL 分區引擎在一個單獨的層中運行,并且可以和任何這樣的層進行相互作用。在MySQL 5.1版中,同一個分區表的所有分區必須使用同一個存儲引擎;例如,不能對一個分區使用MyISAM,而對另一個使用InnoDB。但是,這并不妨礙在同一個 MySQL 服務器中,甚至在同一個數據庫中,對于不同的分區表使用不同的存儲引擎。
?
分區適用于一個表的所有數據和索引;不能只對數據分區而不對索引分區,反之亦然,同時也不能只對表的一部分進行分區。
?
可以通過使用用來創建分區表的CREATE TABLE語句的PARTITION子句的DATA DIRECTORY(數據路徑)和INDEX DIRECTORY(索引路徑)選項,為每個分區的數據和索引指定特定的路徑。此外,MAX_ROWS和MIN_ROWS選項可以用來設定最大和最小的行數,它們可以各自保存在每個分區里。
?
無論使用何種類型的分區,分區總是在創建時就自動的順序編號,且從0開始記錄,記住這一點非常重要。當有一新行插入到一個分區表中時,就是使用這些分區編號來識別正確的分區。例如,如果你的表使用4個分區,那么這些分區就編號為0, 1, 2, 和3。對于RANGE和LIST分區類型,確認每個分區編號都定義了一個分區,很有必要。對HASH分區,使用的用戶函數必須返回一個大于0的整數值。對于KEY分區,這個問題通過MySQL服務器內部使用的 哈希函數自動進行處理。
?
?
3,分區類型:
| RANGE分區 | 按照RANGE分區的表是通過如下一種方式進行分區的,每個分區包含那些分區表達式的值位于一個給定的連續區間內的行。這些區間要連續且不能相互重疊,使用VALUES LESS THAN ?操作符來進行定義。 |
| lIST分區 | 類似于RANGE分區,區別在于LIST分區是基于列值匹配一個離散值集合中的某個值來進行選擇。 |
| HASH分區 | HASH分區主要用來確保數據在預先確定數目的分區中平均分布。在RANGE和LIST分區中,必須明確指定一個給定的列值或列值集合應該保存在哪個分區中;而在HASH分區中,MySQL 自動完成這些工作,你所要做的只是基于將要被哈希的列值指定一個列值或表達式,以及指定被分區的表將要被分割成的分區數量。 |
| KEY分區 | 類似于HASH分區,區別在于KEY分區只支持計算一列或多列,且MySQL 服務器提供其自身的哈希函數。必須有一列或多列包含整數值。 |
??
?
測試實例:
1,range測試實例:
說明:employees表保存有20家音像店的職員記錄,這20家音像店的編號從1到20,按照這種分區方案,在商店1到5工作的職員相對應的所有行被保存在分區P0中,商店6到10的職員保存在P1中,依次類推,大于或等于16的職員都保存在P3中。PARTITION BY RANGE 語法要求每個分區都是按順序進行定義,從最低到最高,AXVALUE 表示最大的可能的整數值,在將來的某個時候,當商店數已經增長到25,30 或更多,可以使用ALTER TABLE語句為商店21-25, 26-30,等等增加新的分區。
?
mysql> CREATE TABLE employees (
??? ->???? id INT NOT NULL,
??? ->???? fname VARCHAR(30),
??? ->???? lname VARCHAR(30),
??? ->???? hired DATE NOT NULL DEFAULT '1970-01-01',
??? ->???? separated DATE NOT NULL DEFAULT '9999-12-31',
??? ->???? job_code INT NOT NULL,
??? ->???? store_id INT NOT NULL
??? -> )
??? -> PARTITION BY RANGE (store_id) (
??? -> PARTITION p0 VALUES LESS THAN (6),
??? -> PARTITION p1 VALUES LESS THAN (11),
??? -> PARTITION p2 VALUES LESS THAN (16),
??? -> PARTITION p3 VALUES LESS THAN MAXVALUE
??? -> );
Query OK, 0 rows affected (0.01 sec)
?
mysql> insert into employees values (1,'xiaoii','xiaowu01','1971-01-01','1972-01-01',1,5);
Query OK, 1 row affected (0.00 sec)
?
mysql> insert into employees values (2,'xiaokk','xiaowu01','1972-01-01','1973-01-01',2,6);
Query OK, 1 row affected (0.00 sec)
?
mysql> insert into employees values (3,'xiaoxx','xiaowu01','1974-01-01','1975-01-01',3,7);
Query OK, 1 row affected (0.00 sec)
?
mysql> insert into employees values (4,'xiaoyy','xiaowu01','1976-01-01','1977-01-01',4,11);
Query OK, 1 row affected (0.00 sec)
?
mysql> insert into employees values (5,'xiaocc','xiaowu01','1978-01-01','1979-01-01',5,12);
Query OK, 1 row affected (0.00 sec)
?
mysql> insert into employees values (6,'xiaoaa','xiaowu01','1980-01-01','1981-01-01',6,16);
Query OK, 1 row affected (0.00 sec)
?
mysql> insert into employees values (7,'xiaott','xiaowu01','1982-01-01','1983-01-01',7,17);
Query OK, 1 row affected (0.00 sec)
?
mysql> insert into employees values (8,'xiaogg','xiaowu01','1984-01-01','1985-01-01',8,20);
Query OK, 1 row affected (0.00 sec)
?
mysql> select * from employees;
+----+--------+----------+------------+------------+----------+----------+
| id | fname? | lname??? | hired????? | separated? | job_code | store_id |
+----+--------+----------+------------+------------+----------+----------+
|? 1 | xiaoii | xiaowu01 | 1971-01-01 | 1972-01-01 |??????? 1 |??????? 5 |
|? 2 | xiaokk | xiaowu01 | 1972-01-01 | 1973-01-01 |??????? 2 |??????? 6 |
|? 3 | xiaoxx | xiaowu01 | 1974-01-01 | 1975-01-01 |??????? 3 |??????? 7 |
|? 4 | xiaoyy | xiaowu01 | 1976-01-01 | 1977-01-01 |??????? 4 |?????? 11 |
|? 5 | xiaocc | xiaowu01 | 1978-01-01 | 1979-01-01 |??????? 5 |?????? 12 |
|? 6 | xiaoaa | xiaowu01 | 1980-01-01 | 1981-01-01 |??????? 6 |?????? 16 |
|? 7 | xiaott | xiaowu01 | 1982-01-01 | 1983-01-01 |??????? 7 |?????? 17 |
|? 8 | xiaogg | xiaowu01 | 1984-01-01 | 1985-01-01 |??????? 8 |?????? 20 |
+----+--------+----------+------------+------------+----------+----------+
8 rows in set (0.00 sec)
?
mysql> explain partitions select * from employees;
+----+-------------+-----------+-------------+------+---------------+------+---------+------+------+-------+
| id | select_type | table???? | partitions? | type | possible_keys | key? | key_len | ref? | rows | Extra |
+----+-------------+-----------+-------------+------+---------------+------+---------+------+------+-------+
|? 1 | SIMPLE????? | employees | p0,p1,p2,p3 | ALL? | NULL????????? | NULL | NULL??? | NULL |??? 8 |?????? |
+----+-------------+-----------+-------------+------+---------------+------+---------+------+------+-------+
1 row in set (0.00 sec)
?
?
mysql> explain partitions select * from employees where store_id=5;
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table???? | partitions | type | possible_keys | key? | key_len | ref? | rows | Extra?????? |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+-------------+
|? 1 | SIMPLE????? | employees | p0?????? ??| ALL? | NULL????????? | NULL | NULL??? | NULL |??? 8 | Using where |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
?
mysql> explain partitions select * from employees where store_id=11;
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table???? | partitions | type | possible_keys | key? | key_len | ref? | rows | Extra?????? |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+-------------+
|? 1 | SIMPLE????? | employees | p2???????? | ALL? | NULL????????? | NULL | NULL??? | NULL |??? 8 | Using where |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
?
mysql> explain partitions select * from employees where store_id=16;
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table???? | partitions | type | possible_keys | key? | key_len | ref? | rows | Extra?????? |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+-------------+
|? 1 | SIMPLE????? | employees | p3???????? | ALL? | NULL????????? | NULL | NULL??? | NULL |??? 8 | Using where |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
?
?
2,LIST測試實例:
假定有20個音像店,店面分布在4個地區,如下表所示:
| 地區 | 商店ID 號 |
| 北區 | 3, 5, 6, 9, 17 |
| 東區 | 1, 2, 10, 11, 19, 20 |
| 西區 | 4, 12, 13, 14, 18 |
| 中心區 | 7, 8, 15, 16 |
?
?
mysql> CREATE TABLE employeeslist (
??? -> id INT NOT NULL,
??? -> fname VARCHAR(30),
??? -> lname VARCHAR(30),
??? -> hired DATE NOT NULL DEFAULT '1970-01-01',
??? -> separated DATE NOT NULL DEFAULT '9999-12-31',
??? -> job_code INT,
??? -> store_id INT
??? -> )
??? -> PARTITION BY LIST(store_id) (
??? -> PARTITION pNorth VALUES IN (3,5,6,9,17),
??? -> PARTITION pEast VALUES IN (1,2,10,11,19,20),
??? -> PARTITION pWest VALUES IN (4,12,13,14,18),
??? -> PARTITION pCentral VALUES IN (7,8,15,16)
??? -> );
Query OK, 0 rows affected (0.00 sec)
?
mysql> insert into employeeslist values (1,'xiaoii','xiaowu01','1971-01-01','1972-01-01',1,1);
Query OK, 1 row affected (0.00 sec)
?
mysql> insert into employeeslist values (2,'xiaokk','xiaowu01','1972-01-01','1973-01-01',2,3);
Query OK, 1 row affected (0.00 sec)
?
mysql> insert into employeeslist values (3,'xiaoxx','xiaowu01','1974-01-01','1975-01-01',3,4);
Query OK, 1 row affected (0.00 sec)
?
mysql> select * from employeeslist;
+----+--------+----------+------------+------------+----------+----------+
| id | fname? | lname??? | hired????? | separated? | job_code | store_id |
+----+--------+----------+------------+------------+----------+----------+
|? 2 | xiaokk | xiaowu01 | 1972-01-01 | 1973-01-01 |??????? 2 |??????? 3 |
|? 1 | xiaoii | xiaowu01 | 1971-01-01 | 1972-01-01 |??????? 1 |??????? 1 |
|? 3 | xiaoxx | xiaowu01 | 1974-01-01 | 1975-01-01 |??????? 3 |??????? 4 |
+----+--------+----------+------------+------------+----------+----------+
3 rows in set (0.00 sec)
?
mysql> explain partitions select * from employeeslist where store_id=1;
+----+-------------+---------------+------------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table???????? | partitions | type | possible_keys | key? | key_len | ref? | rows | Extra?????? |
+----+-------------+---------------+------------+------+---------------+------+---------+------+------+-------------+
|? 1 | SIMPLE????? | employeeslist | pEast????? | ALL? | NULL????????? | NULL | NULL??? | NULL |??? 4 | Using where |
+----+-------------+---------------+------------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
?
mysql> explain partitions select * from employeeslist where store_id=3;
+----+-------------+---------------+------------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table???????? | partitions | type | possible_keys | key? | key_len | ref? | rows | Extra?????? |
+----+-------------+---------------+------------+------+---------------+------+---------+------+------+-------------+
|? 1 | SIMPLE????? | employeeslist | pNorth???? | ALL? | NULL????????? | NULL | NULL??? | NULL |??? 4 | Using where |
+----+-------------+---------------+------------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
?
mysql> explain partitions select * from employeeslist where store_id=4;
+----+-------------+---------------+------------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table???????? | partitions | type | possible_keys | key? | key_len | ref? | rows | Extra?????? |
+----+-------------+---------------+------------+------+---------------+------+---------+------+------+-------------+
|? 1 | SIMPLE????? | employeeslist | pWest????? | ALL? | NULL????????? | NULL | NULL??? | NULL |??? 4 | Using where |
+----+-------------+---------------+------------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
?
?
?
?
?
3,HASH測試實例:
?
mysql> CREATE TABLE employeeshash (
??? -> id INT NOT NULL,
??? -> fname VARCHAR(30),
??? -> lname VARCHAR(30),
??? -> hired DATE NOT NULL DEFAULT '1970-01-01',
??? -> separated DATE NOT NULL DEFAULT '9999-12-31',
??? -> job_code INT,
??? -> store_id INT
??? -> )
??? -> PARTITION BY HASH(store_id)
??? -> PARTITIONS 4;
Query OK, 0 rows affected (0.00 sec)
?
mysql> insert into employeeshash values (1,'xiaoii','xiaowu01','1971-01-01','1972-01-01',1,1);
Query OK, 1 row affected (0.00 sec)
?
mysql> insert into employeeshash values (2,'xiaokk','xiaowu01','1972-01-01','1973-01-01',2,3);
Query OK, 1 row affected (0.00 sec)
?
mysql> insert into employeeshash values (3,'xiaoxx','xiaowu01','1974-01-01','1975-01-01',3,6);
Query OK, 1 row affected (0.00 sec)
?
mysql> insert into employeeshash values (4,'xiaoxx','xiaowu01','1974-01-01','1975-01-01',3,9);
Query OK, 1 row affected (0.00 sec)
?
?
mysql> select * from employeeshash;
+----+--------+----------+------------+------------+----------+----------+
| id | fname? | lname??? | hired????? | separated? | job_code | store_id |
+----+--------+----------+------------+------------+----------+----------+
|? 1 | xiaoii | xiaowu01 | 1971-01-01 | 1972-01-01 |??????? 1 |??????? 1 |
|? 4 | xiaoxx | xiaowu01 | 1974-01-01 | 1975-01-01 |??????? 3 |??????? 9 |
|? 3 | xiaoxx | xiaowu01 | 1974-01-01 | 1975-01-01 |??????? 3 |??????? 6 |
|? 2 | xiaokk | xiaowu01 | 1972-01-01 | 1973-01-01 |??????? 2 |??????? 3 |
+----+--------+----------+------------+------------+----------+----------+
4 rows in set (0.00 sec)
?
mysql> explain partitions select * from employeeshash;
+----+-------------+---------------+-------------+------+---------------+------+---------+------+------+-------+
| id | select_type | table???????? | partitions? | type | possible_keys | key? | key_len | ref? | rows | Extra |
+----+-------------+---------------+-------------+------+---------------+------+---------+------+------+-------+
|? 1 | SIMPLE????? | employeeshash | p0,p1,p2,p3 | ALL? | NULL????????? | NULL | NULL??? | NULL |??? 5 |?????? |
+----+-------------+---------------+-------------+------+---------------+------+---------+------+------+-------+
1 row in set (0.00 sec)
?
mysql> explain partitions select * from employeeshash where store_id=1;
+----+-------------+---------------+------------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table???????? | partitions | type | possible_keys | key? | key_len | ref? | rows | Extra?????? |
+----+-------------+---------------+------------+------+---------------+------+---------+------+------+-------------+
|? 1 | SIMPLE????? | employeeshash | p1???????? | ALL? | NULL????????? | NULL | NULL??? | NULL |??? 5 | Using where |
+----+-------------+---------------+------------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
?
mysql> explain partitions select * from employeeshash where store_id=6;
+----+-------------+---------------+------------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table???????? | partitions | type | possible_keys | key? | key_len | ref? | rows | Extra?????? |
+----+-------------+---------------+------------+------+---------------+------+---------+------+------+-------------+
|? 1 | SIMPLE????? | employeeshash | p2???????? | ALL? | NULL????????? | NULL | NULL??? | NULL |??? 5 | Using where |
+----+-------------+---------------+------------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
?
mysql> explain partitions select * from employeeshash where store_id=3;
+----+-------------+---------------+------------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table???????? | partitions | type | possible_keys | key? | key_len | ref? | rows | Extra?????? |
+----+-------------+---------------+------------+------+---------------+------+---------+------+------+-------------+
|? 1 | SIMPLE????? | employeeshash | p3???????? | ALL? | NULL ?????????| NULL | NULL??? | NULL |??? 5 | Using where |
+----+-------------+---------------+------------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
??
?
4,子分區測試實例:
在MySQL 5.1中,可以對RANGE或LIST分區了的表再進行子分區。子分區既可以使用HASH希分區,也可以使用KEY分區。這也被稱為復合分區(composite partitioning),子分區是分區表中每個分區的再次分割。例如,考慮下面的CREATE TABLE 語句:
?
mysql> CREATE TABLE ts (id INT, purchased DATE)
??? -> PARTITION BY RANGE(YEAR(purchased))
??? -> SUBPARTITION BY HASH(TO_DAYS(purchased))
??? -> SUBPARTITIONS 2
??? -> (
??? -> PARTITION p0 VALUES LESS THAN (1990),
??? -> PARTITION p1 VALUES LESS THAN (2000),
??? -> PARTITION p2 VALUES LESS THAN MAXVALUE
??? -> );
?
Query OK, 0 rows affected (0.03 sec)
mysql> desc ts;
+-----------+---------+------+-----+---------+-------+
| Field???? | Type??? | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+-------+
| id??????? | int(11) | YES? |???? | NULL??? |?????? |
| purchased | date??? | YES? |???? | NULL??? |?????? |
+-----------+---------+------+-----+---------+-------+
2 rows in set (0.00 sec)
?
表ts 有3個RANGE分區。這3個分區中的每一個分區——p0, p1, 和 p2 ——又被進一步分成了2個子分區。實際上,整個表被分成了3 * 2 = 6個分區。但是,由于PARTITION BY RANGE子句的作用,這些分區的頭2個只保存“purchased”列中值小于1990的那些記錄。
?
?
?
分區管理:
MySQL 5.1 可以通過使用ALTER TABLE 命令對分區進行 添加、刪除、重新定義、合并或拆分。
?
1,RANGE和LIST分區的管理:
?
| ALTER TABLE chlotte DROP PARITION p1 ? | 刪除chlotte表中名稱為p1的分區及p1分區中的所有數據,但NDBCLUSTER存儲引擎不支持此語法。 |
| TRUNCATE TABLE chlotte; | 只刪除分區中的數據,保留表的定義和表的分區模式。 |
| ALTER TABLE ... REORGANIZE PARTITION | 改變表的分區而又不丟失數據。 |
| ALTER TABLE ... ADD PARTITION | 增加一個新的RANGE或LIST分區到一個前面已經分區了的表,對于RANGE分區的表,只可以使用ADD PARTITION添加新的分區到分區列表的高端。 |
| ALTER TABLE tbl_name REORGANIZE PARTITION partition_list INTO (partition_definitions); | 其中,tbl_name 是分區表的名稱,partition_list 是通過逗號分開的、一個或多個將要被改變的現有分區的列,partition_definitions 是一個是通過逗號分開的、新分區定義的列表,使用“REORGANIZE PARTITION”拆分或合并分區,沒有數據丟失。 |
?
?
2,HASH和KEY分區的管理:
?
| ALTER TABLE chlotte COALESCE PARTITION 6; | 把chlotte表的分區數量由7個減少到6個 |
| ALTER TABLE chlotte COALESCE PARTITION 8; | 把chlotte表的分區數量從6個增加到8個 |
?
??
分區維護:
?Table maintenance of partitioned tables can be accomplished using the statements CHECK TABLE, OPTIMIZE TABLE, ANALYZE TABLE, and REPAIR TABLE, which are supported for partitioned tables as of MySQL 5.1.27.
?
| ALTER TABLE t1 REBUILD PARTITION p0, p1; | 重建分區: 這和先刪除保存在分區中的所有記錄,然后重新插入它們,具有同樣的效果。它可用于整理分區碎片。 |
| ALTER TABLE t1 OPTIMIZE PARTITION p0, p1; | 優化分區:如果從分區中刪除了大量的行,或者對一個帶有可變長度的行作了許多修改,用來收回沒有使用的空間,并整理分區數據文件的碎片。 |
| ALTER TABLE t1 ANALYZE PARTITION p3; | 分析分區:讀取并保存分區的鍵分布。 |
| ALTER TABLE t1 REPAIR PARTITION p0,p1; | 修復分區: 修復被破壞的分區。 |
| ALTER TABLE trb3 CHECK PARTITION p1; | 檢查分區: 可以使用幾乎與對非分區表使用CHECK TABLE 相同的方式檢查分區。 |
?
?
?
分區的限制:
1,從mysql 5.1.12 開始不支持: 存儲過程,存儲函數,用戶自定義函數,用戶變量。
2,分區表不支持外鍵。
轉載于:https://blog.51cto.com/chlotte/372943
總結
以上是生活随笔為你收集整理的Partition学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: csv文件怎么打开?csv是什么文件?
- 下一篇: AAA学习笔记