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


一、        分區的概念
二、        為什么使用分區?(優點)
三、        分區類型
四、        子分區
五、        對分區進行修改(增加、刪除、分解、合並)
六、        不同引擎的分區特性
七、        分區的限制性



分區概念

分區針對不同的數據庫,具有不同的特性。在這里專門針對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分區表局限性總結

Mysql5.1已經發行很久了,本文根據官方文檔的翻譯和自己的一些測試,對Mysql分區表的局限性做了一些總結,因為個人能力以及測試環境的原因,有可能有錯誤的地方,還請大家看到能及時指出,當然有興趣的朋友可以去官方網站查閱。

本文測試的版本

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

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

在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.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 分區表的所有分區或者子分區的存儲引擎必須相同,這個限制也許會在以后的版本取消。
不指定任何引擎(使用默認引擎)。
所有分區或者子分區指定相同引擎。

三、關於函數的限制
在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()

四、其他限制

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM