MySQL partition分區
分區概念
分區針對不同的數據庫,具有不同的特性。在這裡專門針對MySQL數據庫而言。在MySQL數據庫裡,分區這個概念是從mysql 5.1才開始提供的。不過目前只有在mysql advanced版本裡才提供。
分區是把數據庫、或它的組成部分(比如表)分成幾個小部分。而且專門介紹的都是’水平分區’,即對表的行進行劃分。
分區的優點
1. 可以提高數據庫的性能;
2. 對大表(行較多)的維護更快、更容易,因為數據分布在不同的邏輯文件上;
3. 刪除分區或它的數據是容易的,因為它不影響其他表。
注意:pruning,即截斷。意思是說當你查詢時,只掃描所需要查詢的分區。。其他部分不會掃描。。這就大大地提高了性能。
分區類型
分區具有如下4種類型:
Range分區:是對一個連續性的行值,按范圍進行分區;比如:id小於100;id大於100小於200;
List分區:跟range分區類似,不過它存放的是一個離散值的集合。
Hash分區:對用戶定義的表達式所返回的值來進行分區。可以寫partitions (分區數目),或直接使用分區語句,比如partition p0 values in…..。
Key分區:與hash分區類似,只不過分區支持一列或多列,並且MySQL服務器自身提供hash函數。
具體描述:
分區語法:
create table t(id int,name varchar(20)) engine=myisam partition by range(id);
按range范圍進行分區: create table orders_range ( id int auto_increment primary key, customer_surname varchar (30), store_id int, salesperson_id int, order_Date date, note varchar(500) ) engine=myisam partition by range(id) ( partition p0 values less than(5), partition p1 values less than(10), partition p3 values less than(15) );
其實上面的分區創建,我們可知道,它的表類型為myisam,而每個分區的引擎也是myisam,這個可以通過show create table tablename查看。當我們插入數據到表裡時,如果要查看小於8的信息,它之後檢索p0和p12個分區。這樣就非常快速了。
按list進行分區:
create table orders_list ( id int auto_increment, customer_surname varchar(30), store_id int, salesperson_id int, order_Date date, note varchar(500), index idx(id) ) engine=myisam partition by list(store_id) ( partition p0 values in(1,3), partition p1 values in2,4,6), partition p3 values in(10) );
list 分區只能把你插入的值放在某個已定的分區裡,若沒有那個值,,就顯示不能插入。
按hash進行分區:
create table orders_hash ( id int auto_increment primary key, cutomer_surname varchar(30), store_id int, salesperon_id int, order_date date, note varcahr(500) ) engine=myisam partition by hash(id) partitions 4;
如果分為4個分區,那當我插入數據時,哪些數據是放在哪些分區裡呢? 當我對某個id值進行檢索時,它明確說放到哪個分區裡?或者說是有什麼內部機制?
使用hash分區,最主要就是確保數據的分配,它是基於create table時提供的表達式。不必定義單獨的分區,只要使用partitions關鍵字和所需要分多少個區的數字。語句如上所述。
按key進行分區:
create table orders_key ( id int auto_increment, customer_surname varchar(30), store_id int, alesperson_id int, order_Date date, note varcahr(500), index_idx(id) ) engine=myisam partition by key(order_date) partitions 4; 這個分區類似於hash分區,除了MySQL服務器使用它本身的hash表達式,不像其他類型的分區,不必要求使用一個int或null的表達式。
按子分區進行分區:
create table orders_range ( id int auto_increment primary key, customer_surname varchar(30), store_id int, salesperson_id int, order_Date date, note varchar(500) ) engine=myisam partition by range(id) subpartition by hash(store_id) subpartitions 2 ( partition p0 values less than(5), partition p1 values less than(10), partition p3 values less than(15) );
當把數據插入到表中時,那什麼數據是放在子分區裡呢?
================================================
MySQL partition分區II( 續)
獲得分區信息
MySQL可以通過如下方式來獲取分區表的信息:
Show create tabe table; //表詳細結構
show table status; //表的各種參數狀態
select * from information_schema.partitions;//通過數據字典來查看表的分區信息
explain partitions select * from table; // 通過此語句來顯示掃描哪些分區,及他們是如何使用的.
對分區進行修改 (修改、合並、重定義分區)
修改分區
修改部分分區:
由於我們平常使用的數據庫大都是動態運行的,所以只對某個表分區進行修改就OK了。
可以對range或list表分區進行add或drop,也可以對hash或key分區表進行合並或分解。這些動作都在alter table語句裡進行。
使用add partition 關鍵字來對已有分區表進行添加。
Alter table orders_range add partition ( Partition p5 values less than(maxvalue) )
Reorganize partition關鍵字可以對表的部分分區或全部分區進行修改,並且不會丟失數據。
Splitting即分解一個已有分區:
Alter table orders_range reorganize partition p0 into ( partition n0 values less than(5000), partition n1 values less than(10000) );
Merge分區:像上面把p0分成n0和n1,現在在把2個合並為一個。
Alter table orders_range reorganize partition n0,n1 into ( Partition p0 values less than(10000) );
修改所有的分區:在into關鍵字之前或之後都指定多個分區
Alter table orders_range reorganize partition p0,p1,p2,p3,p4,p5 into ( Partition r0 values less than(25000), Partition r1 values less than(50000), Partition r2 values less than(maxvalue) );
Coalesce 合並分區:Merge分區的另一種方法就是alter table….coalesce partition語句,你不能對hash或key分區進行刪除
Alter table orders_key coalesce partition1;
Redefine重定義分區
Alter table orders_range partition by hash(id) partitions 4;
對分區進行刪除 (刪除、刪除所有分區)
Drop 分區:
可以對range或list類型的分區通過drop partition 關鍵字進行刪除
Alter table orders_range drop partition p0;
注意:
1.對這個分區進行刪除時,你會把這個分區的所有數據進行刪除,與delete語句相等;
2.在做alter table..drop partition時,必須有drop權限;
3.運行這個刪除命令,它不會返回刪除了的行,可以通過select count()語句查看。
如果想對多個分區進行刪除,可以使用如下命令語句:Alter table orders_range drop partition p1,p2;
刪除所有分區
通過如下命令語句刪除表中所有分區,最後是一個正規表.
Alter table orders_range remove partitioning;
當進行分區操作,了解對性能所產生的影響是非常有幫助的:
1.創建分區表比無分區的正規表要稍微慢些;
2.通過alter table….drop partition語句進行刪除比delete語句要快些;
3.在range或list分區類型上添加分區(alter table…add partition語句)是相當快的,因為沒有移動數據到新分區裡。
4.當在一個key或hash類型的分區上執行alter table….add partition語句,要依賴表中已有多少行記錄,數據越多,它添加一個新分區的時間就越長。當創建一個表時,使用線性hash或線性key分區是相當快的。
5.對成百上千的行記錄,進行alter table …coalesce partition, alter table …reorganize partition, alter table…partition by操作命令時,是相當慢的。
6.當使用add partition命令時,線性hash和線性key分區會使coalesce partition操作更快, alter table …remove partitioning比其他都要快,因為mysql沒有要求哪個文件來替代行,即使是移動數據。
各種存儲引擎的分區
MySQL分區可以對所有MySQL支持的存儲引擎進行分區,比如:myisam, innodb, archive, NDBcluster(只可以線性key),falcon, 不支持分區的引擎:merge, federated, csv, blackhole
注意:所有分區和子分區的表類型要一致;
索引維護要依賴表類型;
鎖住某些行,也依賴於存儲引擎;
分區也屬於存儲引擎的頂層,所以進行update和insert時,性能不會產生很大的影響。
各種存儲引擎使用分區時的限制:
MyISAM引擎:
Myisam引擎允許在使用分區時,把表的不同部分存儲在不同地方,包括索引目錄和數據目錄。
下面是一個關於把數據分布到4個不同的物理磁盤上的myisam分區。
Create table orders_hash2 ( Id int auto_increment primary key, …… ) engine=myisam Partition by hash(id) ( Partition p0 index directory=’/data0/orders/idx’ data directory=’ /data0/orders/data’, Partition p1 index directory=’/data1/orders/idx’ data directory=’ /data1/orders/data’, Partition p2 index directory=’/data2/orders/idx’ data directory=’ /data2/orders/data’, Partition p3 index directory=’/data3/orders/idx’ data directory=’ /data3/orders/data’, );
注意:上面的具體4個分布,在windows系統上目前還不支持。
InnoDB引擎:
Innodb的分區管理與myisam引擎的管理是不同的。
分區的限制性
下面講到的是一些關於MySQL分區的限制性約束
常見的限制:
所有的分區必須使用同種引擎;
批量裝載很慢;
每個表的最大分區數為1024;
不支持三維數據類型(GIS);
不能對臨時表進行分區;
不可能對日志表進行分區;
外鍵和索引方面:
不支持外鍵;
不支持全文表索引;
不支持load cache和load index into cache;
子分區方面:
只允許對range和list類型的分區再進行分區;
子分區的類型只允許是hash或key.
分區表達式方面:
Range,list, hash分區必須是int類型;
Key分區不可以有text,blob類型;
不允許使用UDF,存儲函數,變量,操作符(|,,^,<<,>>,~)和一些內置的函數;
在表創建之後sql mode不可以改變;
在分區表達式中,不允許子查詢;
分區表達式中必須包括至少一個列的引用,唯一索引列也可以(包括主鍵)