MYSQL之水平分區----MySQL partition分區I(5.1)

1、        分區的概念
2、        爲何使用分區?(優勢)
3、        分區類型
4、        子分區
5、        對分區進行修改(增長、刪除、分解、合併)
6、        不一樣引擎的分區特性
7、        分區的限制性



分區概念

分區針對不一樣的數據庫,具備不一樣的特性。在這裏專門針對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了。
能夠對rangelist表分區進行adddrop,也能夠對hashkey分區表進行合併或分解。這些動做都在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分紅n0n1,如今在把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語句,你不能對hashkey分區進行刪除
Alter table orders_key coalesce partition1;

Redefine重定義分區
Alter table orders_range partition by hash(id) partitions 4;

對分區進行刪除 (刪除、刪除全部分區)
Drop 分區:
能夠對rangelist類型的分區經過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不能夠改變; 在分區表達式中,不容許子查詢; 分區表達式中必須包括至少一個列的引用,惟一索引列也能夠(包括主鍵) =================================================== Mysql分區表侷限性總結
html

Mysql5.1已經發行好久了,本文根據官方文檔的翻譯和本身的一些測試,對Mysql分區表的侷限性作了一些總結,由於我的能力以及測試環境的緣由,有可能有錯誤的地方,還請你們看到能及時指出,固然有興趣的朋友能夠去官方網站查閱。mysql

本文測試的版本sql

mysql> select version(); +------------+ | version() | +------------+ | 5.1.33-log | +------------+ 1 row in set (0.00 sec) 

1、關於Partitioning Keys, Primary Keys, and Unique Keys的限制shell

在5.1中分區表對惟一約束有明確的規定,每個惟一約束必須包含在分區表的分區鍵(也包括主鍵約束)。
這句話也許很差理解,咱們作幾個實驗:數據庫

CREATE TABLE t1 ( id INT NOT NULL, uid INT NOT NULL, PRIMARY KEY (id) ) PARTITION BY RANGE (id) (PARTITION p0 VALUES LESS THAN(5) ENGINE = INNODB, PARTITION p1 VALUES LESS THAN(10) ENGINE = INNODB );   CREATE TABLE t1 ( id INT NOT NULL, uid INT NOT NULL, PRIMARY KEY (id) ) PARTITION BY RANGE (id) (PARTITION p0 VALUES LESS THAN(5) ENGINE = MyISAM DATA DIRECTORY='/tmp' INDEX DIRECTORY='/tmp', PARTITION p1 VALUES LESS THAN(10) ENGINE = MyISAM DATA DIRECTORY='/tmp' INDEX DIRECTORY='/tmp' );   mysql> CREATE TABLE t1 -> ( id INT NOT NULL, -> uid INT NOT NULL, -> PRIMARY KEY (id), -> UNIQUE KEY (uid) -> ) -> PARTITION BY RANGE (id) -> (PARTITION p0 VALUES LESS THAN(5), -> PARTITION p1 VALUES LESS THAN(10) -> ); ERROR 1503 (HY000): A UNIQUE INDEX must include all columns in the table's partitioning function 

2、關於存儲引擎的限制
2.1 MERGE引擎不支持分區,分區表也不支持merge。
2.2 FEDERATED引擎不支持分區。這限制可能會在之後的版本去掉。
2.3 CSV引擎不支持分區
2.4 BLACKHOLE引擎不支持分區
2.5 在NDBCLUSTER引擎上使用分區表,分區類型只能是KEY(or LINEAR KEY) 分區。
2.6 當升級MYSQL的時候,若是你有使用了KEY分區的表(不論是什麼引擎,NDBCLUSTER除外),那麼你須要把這個表dumped在reloaded。
2.7 分區表的全部分區或者子分區的存儲引擎必須相同,這個限制也許會在之後的版本取消。
不指定任何引擎(使用默認引擎)。
全部分區或者子分區指定相同引擎。windows

3、關於函數的限制
在mysql5.1中創建分區表的語句中,只能包含下列函數:
ABS()
CEILING() and FLOOR() (在使用這2個函數的創建分區表的前提是使用函數的分區鍵是INT類型),例如服務器

mysql> CREATE TABLE t (c FLOAT) PARTITION BY LIST( FLOOR(c) )( -> PARTITION p0 VALUES IN (1,3,5), -> PARTITION p1 VALUES IN (2,4,6) -> );; ERROR 1491 (HY000): The PARTITION function returns the wrong type   mysql> CREATE TABLE t (c int) PARTITION BY LIST( FLOOR(c) )( -> PARTITION p0 VALUES IN (1,3,5), -> PARTITION p1 VALUES IN (2,4,6) -> ); Query OK, 0 rows affected (0.01 sec) 

DAY()
DAYOFMONTH()
DAYOFWEEK()
DAYOFYEAR()
DATEDIFF()
EXTRACT()
HOUR()
MICROSECOND()
MINUTE()
MOD()
MONTH()
QUARTER()
SECOND()
TIME_TO_SEC()
TO_DAYS()
WEEKDAY()
YEAR()
YEARWEEK()less

4、其餘限制ide

4.1 對象限制
下面這些對象在不能出如今分區表達式
Stored functions, stored procedures, UDFs, or plugins.
Declared variables or user variables.函數

4.2 運算限制
支持加減乘等運算出如今分區表達式,可是運算後的結果必須是一個INT或者NULL。 |, &, ^, <<, >>, , ~ 等不容許出如今分區表達式。

4.3 sql_mode限制
官方強烈建議你在建立分區表後,永遠別改變mysql的sql_mode。由於在不一樣的模式下,某些函數或者運算返回的結果可能會不同。

4.4 Performance considerations.(省略)

4.5 最多支持1024個分區,包括子分區。
當你創建分區表包含不少分區但沒有超過1024限制的時候,若是報錯 Got error 24 from storage engine,那意味着你須要增大open_files_limit參數。

4.6 不支持外鍵。MYSQL中,INNODB引擎才支持外鍵。

4.7 不支持FULLTEXT indexes(全文索引),包括MYISAM引擎。

mysql> CREATE TABLE articles ( -> id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, -> title VARCHAR(200), -> body TEXT, -> FULLTEXT (title,body) -> ) -> PARTITION BY HASH(id) -> PARTITIONS 4; ERROR 1214 (HY000): The used table type doesn't support FULLTEXT indexes 

4.8 不支持spatial column types。
4.9 臨時表不能被分區。

mysql> CREATE Temporary TABLE t1 -> ( id INT NOT NULL, -> uid INT NOT NULL, -> PRIMARY KEY (id) -> ) -> PARTITION BY RANGE (id) -> (PARTITION p0 VALUES LESS THAN(5) ENGINE = MyISAM, -> PARTITION p1 VALUES LESS THAN(10) ENGINE = MyISAM -> ); ERROR 1562 (HY000): Cannot create temporary table with partitions 

4.10 log table不支持分區。

mysql> alter table mysql.slow_log PARTITION BY KEY(start_time) PARTITIONS 2; ERROR 1221 (HY000): Incorrect usage of PARTITION and log table 

5.11 分區鍵必須是INT類型,或者經過表達式返回INT類型,能夠爲NULL。惟一的例外是當分區類型爲KEY分區的時候,可使用其餘類型的列做爲分區鍵( BLOB or TEXT 列除外)。

mysql> CREATE TABLE tkc (c1 CHAR) -> PARTITION BY KEY(c1) -> PARTITIONS 4; Query OK, 0 rows affected (0.00 sec)   mysql> CREATE TABLE tkc2 (c1 CHAR) -> PARTITION BY HASH(c1) -> PARTITIONS 4; ERROR 1491 (HY000): The PARTITION function returns the wrong type   mysql> CREATE TABLE tkc3 (c1 INT) -> PARTITION BY HASH(c1) -> PARTITIONS 4; Query OK, 0 rows affected (0.00 sec) 

5.12 分區鍵不能是一個子查詢。 A partitioning key may not be a subquery, even if that subquery resolves to an integer value or NULL

5.13 只有RANG和LIST分區能進行子分區。HASH和KEY分區不能進行子分區。

5.14 分區表不支持Key caches。

mysql> SET GLOBAL keycache1.key_buffer_size=128*1024; Query OK, 0 rows affected (0.00 sec) mysql> CACHE INDEX login,user_msg,user_msg_p IN keycache1; +-----------------+--------------------+----------+---------------------------------------------------------------------+ | Table | Op | Msg_type | Msg_text | +-----------------+--------------------+----------+---------------------------------------------------------------------+ | test.login | assign_to_keycache | status | OK | | test.user_msg | assign_to_keycache | status | OK | | test.user_msg_p | assign_to_keycache | note | The storage engine for the table doesn't support assign_to_keycache | +-----------------+--------------------+----------+---------------------------------------------------------------------+ 3 rows in set (0.00 sec) 

5.15 分區表不支持INSERT DELAYED.

mysql> insert DELAYED into user_msg_p values(18156629,0,0,0,0,0,0,0,0,0); ERROR 1616 (HY000): DELAYED option not supported for table 'user_msg_p' 

5.16 DATA DIRECTORY 和 INDEX DIRECTORY 參數在分區表將被忽略。
這個限制應該不存在了:

mysql> CREATE TABLE t1 -> ( id INT NOT NULL, -> uid INT NOT NULL, -> PRIMARY KEY (id) -> ) -> PARTITION BY RANGE (id) -> (PARTITION p0 VALUES LESS THAN(5) ENGINE = MyISAM DATA DIRECTORY='/tmp' INDEX DIRECTORY='/tmp', -> PARTITION p1 VALUES LESS THAN(10) ENGINE = MyISAM DATA DIRECTORY='/tmp' INDEX DIRECTORY='/tmp' -> ); Query OK, 0 rows affected (0.01 sec) 

5.17 分區表不支持mysqlcheck和myisamchk
在5.1.33版本中已經支持mysqlcheck和myisamchk

./mysqlcheck -u -p -r test user_msg_p; test.user_msg_p OK   ./myisamchk -i /u01/data/test/user_msg_p#P#p0.MYI Checking MyISAM file: /u01/data/test/user_msg_p#P#p0.MYI Data records: 4423615 Deleted blocks: 0 - check file-size - check record delete-chain - check key delete-chain - check index reference - check data record references index: 1 Key: 1: Keyblocks used: 98% Packed: 0% Max levels: 4 Total: Keyblocks used: 98% Packed: 0%   User time 0.97, System time 0.02 Maximum resident set size 0, Integral resident set size 0 Non-physical pagefaults 324, Physical pagefaults 0, Swaps 0 Blocks in 0 out 0, Messages in 0 out 0, Signals 0 Voluntary context switches 1, Involuntary context switches 5 

5.18 分區表的分區鍵建立索引,那麼這個索引也將被分區。分區鍵沒有全局索引一說。
5.19 在分區表使用ALTER TABLE … ORDER BY,只能在每一個分區內進行order by。


=================================================

MySQL 分區(Partition)腳本

MySQL 5.1 中新特性分區(partition) shell 腳本。注意 MySQL 只支持小於等於 1024 個分區。

 

#!/bin/sh


# Set these values
PART=0
ORI=5000
STEP=5000
MAX=3000000

for NUM in `seq -f %f $ORI $STEP $MAX | cut -d. -f1` do         echo 「PARTITION $PART VALUES LESS THAN ($NUM),」 >> /tmp/partition.sql         part=`expr $PART + 1` done echo 「PARTITION $PART VALUES LESS THAN MAXVALUE >> /tmp/partition.sql

相關文章
相關標籤/搜索