mysql分區表

1、       mysql分區簡介

數據庫分區mysql

數據庫分區是一種物理數據庫設計技術。雖然分區技術能夠實現不少效果,但其主要目的是爲了在特定的SQL操做中減小數據讀寫的總量以縮減sql語句的響應時間,同時對於應用來講分區徹底是透明的。算法

MYSQL的分區主要有兩種形式:水平分區和垂直分區sql

 

水平分區(HorizontalPartitioning)數據庫

這種形式的分區是對根據表的行進行分區,經過這樣的方式不一樣分組裏面的物理列分割的數據集得以組合,從而進行個體分割(單分區)或集體分割(1個或多個分區)。
全部在表中定義的列在每一個數據集中都能找到,因此表的特性依然得以保持。水平分區必定要經過某個屬性列來分割。常見的好比年份,日期等。express

 

垂直分區(VerticalPartitioning)服務器

這種分區方式通常來講是經過對錶的垂直劃分來減小目標表的寬度,使某些特定的列被劃分到特定的分區,每一個分區都包含了其中的列所對應全部行。
能夠用  showvariables like '%partition%';mysql優化

命令查詢當前的mysql數據庫版本是否支持分區。less

分區的做用:數據庫性能的提高和簡化數據管理數據庫設計

在掃描操做中,mysql優化器只掃描保護數據的那個分區以減小掃描範圍得到性能的提升。ide

分區技術使得數據管理變得簡單,刪除某個分區不會對另外的分區形成影響,分區有系統直接管理不用手工干預。

mysql從5.1版本開始支持分區。每一個分區的名稱是不區分大小寫。同個表中的分區表名稱要惟一。

2、       mysql分區類型

根據所使用的不一樣分區規則能夠分紅幾大分區類型。

RANGE 分區:

基於屬於一個給定連續區間的列值,把多行分配給分區。 

LIST 分區:

相似於按RANGE分區,區別在於LIST分區是基於列值匹配一個離散值集合中的某個值來進行選擇。

HASH分區:

基於用戶定義的表達式的返回值來進行選擇的分區,該表達式使用將要插入到表中的這些行的列值進行計算。這個函數能夠包含MySQL中有效的、產生非負整數值的任何表達式。

KEY
分區:相似於按HASH分區,區別在於KEY分區只支持計算一列或多列,且MySQL服務器提供其自身的哈希函數。必須有一列或多列包含整數值。

複合分區:

基於RANGE/LIST 類型的分區表中每一個分區的再次分割。子分區能夠是 HASH/KEY 等類型。

 

3、       mysql分區表經常使用操做示例

以部門員工表爲例子: 

1)       建立range分區

 

createtable emp

(empno varchar(20notnull ,

empname varchar(20),

deptno int,

birthdate date,

salary int

)

partition by range(salary)

(

partition p1 values less than (1000),

partition p2 values less than (2000),

partition p3 values less than maxvalue

);

以員工工資爲依據作範圍分區。

 

createtable emp

(empno varchar(20notnull ,

empname varchar(20),

deptno int,

birthdate date notnull,

salary int

)

partition by range(year(birthdate))

(

partition p1 values less than (1980),

partition p2 values less than (1990),

partition p3 values less than maxvalue

);

year(birthdate)表達式(計算員工的出生日期)做爲範圍分區依據。這裏最值得注意的是表達式必須有返回值。

 

2)       建立list分區

 

createtable emp

(empno  varchar(20notnull ,

empname varchar(20),

deptno  int,

birthdate datenotnull,

salary int

)

partition by list(deptno)

(

partition p1 valuesin  (10),

partition p2 valuesin  (20),

partition p3 valuesin  (30)

);

以部門做爲分區依據,每一個部門作一分區。

 

3)       建立hash分區

HASH分區主要用來確保數據在預先肯定數目的分區中平均分佈。在RANGE和LIST分區中,必須明確指定一個給定的列值或列值集合應該保存在哪一個分區中;而在HASH分區中,MySQL 自動完成這些工做,你所要作的只是基於將要被哈希的列值指定一個列值或表達式,以及指定被分區的表將要被分割成的分區數量。

createtable emp

(empno varchar(20notnull ,

empname varchar(20),

deptno int,

birthdate datenotnull,

salary int

)

partition by hash(year(birthdate))

partitions 4;

4)       建立key分區

按照KEY進行分區相似於按照HASH分區,除了HASH分區使用的用戶定義的表達式,而KEY分區的哈希函數是由MySQL 服務器提供,服務器使用其本身內部的哈希函數,這些函數是基於與PASSWORD()同樣的運算法則。「CREATE TABLE ...PARTITION BY KEY」的語法規則相似於建立一個經過HASH分區的表的規則。它們惟一的區別在於使用的關鍵字是KEY而不是HASH,而且KEY分區只採用一個或多個列名的一個列表。 

createtable emp

(empno varchar(20notnull ,

empname varchar(20),

deptno int,

birthdate datenotnull,

salary int

)

partition bykey(birthdate)

partitions 4;

 

 

5)       建立複合分區

 

range - hash(範圍哈希)複合分區

 

createtable emp

(empno varchar(20notnull ,

empname varchar(20),

deptno int,

birthdate datenotnull,

salary int

)

partition by range(salary)

subpartition by hash(year(birthdate))

subpartitions 3

(

partition p1 values less than (2000),

partition p2 values less than maxvalue

);

range- key複合分區

createtable emp

(empno varchar(20notnull ,

empname varchar(20),

deptno int,

birthdate datenotnull,

salary int

)

partition by range(salary)

subpartition bykey(birthdate)

subpartitions 3

(

partition p1 values less than (2000),

partition p2 values less than maxvalue

);

list - hash複合分區

CREATETABLE emp (

empno varchar(20NOTNULL,

empname varchar(20) ,

deptno int,

birthdate dateNOTNULL,

salary int

)

PARTITION BY list (deptno)

subpartition by hash(year(birthdate))

subpartitions 3

(

PARTITION p1 VALUESin  (10),

PARTITION p2 VALUESin  (20)

)

;

list - key 複合分區

 

CREATETABLE empk (

empno varchar(20NOTNULL,

empname varchar(20) ,

deptno int,

birthdate dateNOTNULL,

salary int

)

PARTITION BY list (deptno)

subpartition bykey(birthdate)

subpartitions 3

(

PARTITION p1 VALUESin  (10),

PARTITION p2 VALUESin  (20)

)

;

6)       分區表的管理操做

刪除分區:

altertable emp drop partition p1;

不能夠刪除hash或者key分區。

一次性刪除多個分區,altertable emp drop partition p1,p2;

增長分區:

altertable emp add partition (partition p3 values less than (4000));

altertable empl add partition (partition p3 valuesin (40));

分解分區:

Reorganizepartition關鍵字能夠對錶的部分分區或所有分區進行修改,而且不會丟失數據。分解先後分區的總體範圍應該一致。

altertable te

reorganize partition p1 into

(

partition p1 values less than (100),

partition p3 values less than (1000)

); ----不會丟失數據

合併分區:

Merge分區:把2個分區合併爲一個。
altertable te

reorganize partition p1,p3 into

(partition p1 values less than (1000));

----不會丟失數據

 

從新定義hash分區表:

Altertable emp partition by hash(salary)partitions 7;

----不會丟失數據

從新定義range分區表:

Altertable emp partitionbyrange(salary) 

(

partition p1 values less than (2000),

partition p2 values less than (4000)

); ----不會丟失數據

 

刪除表的全部分區:


Altertable emp removepartitioning;--不會丟失數據

 

重建分區:

這和先刪除保存在分區中的全部記錄,而後從新插入它們,具備一樣的效果。它可用於整理分區碎片。 

ALTERTABLE emp rebuild partitionp1,p2;

優化分區:

若是從分區中刪除了大量的行,或者對一個帶有可變長度的行(也就是說,有VARCHAR,BLOB,或TEXT類型的列)做了許多修改,可使用「ALTER TABLE ... OPTIMIZE PARTITION」來收回沒有使用的空間,並整理分區數據文件的碎片。 

ALTERTABLE emp optimize partition p1,p2;

分析分區:

讀取並保存分區的鍵分佈。

ALTERTABLE emp analyze partition p1,p2;

 

修補分區:

修補被破壞的分區。 

ALTERTABLE emp repairpartition p1,p2;

 

檢查分區:

可使用幾乎與對非分區表使用CHECK TABLE 相同的方式檢查分區。

ALTERTABLE emp CHECK partition p1,p2;

這個命令能夠告訴你表emp的分區p1,p2中的數據或索引是否已經被破壞。若是發生了這種狀況,使用「ALTER TABLE ... REPAIR PARTITION」來修補該分區。 

 

 

【mysql分區表的侷限性】

1.      在5.1版本中分區表對惟一約束有明確的規定,每個惟一約束必須包含在分區表的分區鍵(也包括主鍵約束)。

 

CREATETABLE emptt (

empno varchar(20NOTNULL  ,

empname varchar(20),

deptno int,

birthdate dateNOTNULL,

salary int ,

primarykey (empno)

)

PARTITION BY range (salary)

(

PARTITION p1 VALUES less than (100),

PARTITION p2 VALUES less than (200)

);

這樣的語句會報錯。MySQL Database Error: A PRIMARY KEY must include allcolumns in the table's partitioning function;

CREATETABLE emptt (

empno varchar(20NOTNULL  ,

empname varchar(20) ,

deptno int(11),

birthdate dateNOTNULL,

salary int(11) ,

primarykey (empno,salary)

)

PARTITION BY range (salary)

(

PARTITION p1 VALUES less than (100),

PARTITION p2 VALUES less than (200)

);

在主鍵中加入salary列就正常。

 

2.      MySQL分區處理NULL值的方式

若是分區鍵所在列沒有notnull約束。

若是是range分區表,那麼null行將被保存在範圍最小的分區。

若是是list分區表,那麼null行將被保存到list爲0的分區。

在按HASH和KEY分區的狀況下,任何產生NULL值的表達式mysql都視同它的返回值爲0。

爲了不這種狀況的產生,建議分區鍵設置成NOT NULL。

 

3.      分區鍵必須是INT類型,或者經過表達式返回INT類型,能夠爲NULL。惟一的例外是當分

區類型爲KEY分區的時候,可使用其餘類型的列做爲分區鍵( BLOB or TEXT 列除外)。

 

4.      對分區表的分區鍵建立索引,那麼這個索引也將被分區,分區鍵沒有全局索引一說。

5.      只有RANG和LIST分區能進行子分區,HASH和KEY分區不能進行子分區。

6.      臨時表不能被分區。

 

4、       獲取mysql分區表信息的幾種方法

1.     show create table 表名
能夠查看建立分區表的create語句 

2.     show table status 
能夠查看錶是否是分區表 

3.     查看information_schema.partitions表 
select 
  partition_name part,  
  partition_expression expr,  
  partition_description descr,  
  table_rows  
from information_schema.partitions  where 
  table_schema = schema()  
  and table_name='test';  
能夠查看錶具備哪幾個分區、分區的方法、分區中數據的記錄數等信息 

4.     explain partitions select語句
經過此語句來顯示掃描哪些分區,及他們是如何使用的.

 

5、       分區表性能比較

1.     建立兩張表: part_tab(分區表),no_part_tab(普通表)

CREATE TABLEpart_tab 

( c1 int defaultNULL, c2 varchar2(30) default NULL, c3 date not null) 

PARTITION BYRANGE(year(c3)) 

(PARTITION p0VALUES LESS THAN (1995),

PARTITION p1 VALUESLESS THAN (1996) , 

PARTITION p2 VALUESLESS THAN (1997) ,

PARTITION p3 VALUESLESS THAN (1998) ,

 PARTITION p4 VALUES LESS THAN (1999) ,

PARTITION p5 VALUESLESS THAN (2000) , 

PARTITION p6 VALUESLESS THAN (2001) ,

PARTITION p7 VALUESLESS THAN (2002) , 

PARTITION p8 VALUESLESS THAN (2003) ,

PARTITION p9 VALUESLESS THAN (2004) , 

PARTITION p10VALUES LESS THAN (2010),

PARTITION p11VALUES LESS THAN (MAXVALUE) );

CREATE TABLE no_part_tab

( c1 int defaultNULL, c2 varchar2(30) default NULL, c3 date not null);

 

2.     用存儲過程插入800萬條數據

CREATE PROCEDUREload_part_tab()

    begin

    declare v int default 0;

    while v < 8000000

    do

        insert into part_tab

        values (v,'testingpartitions',adddate('1995-01-01',(rand(v)*36520)mod 3652));

         set v = v + 1;

    end while;

end;

insert into no_part_tab  select * frompart_tab;

3.     測試sql性能

查詢分區表:

selectcount(*) from part_tab where c3 > date '1995-01-01'and c3 < date '1995-12-31';

+----------+
| count(*) |
+----------+
|   795181 |
+----------+
1 row in set (2.62 sec)

查詢普通表:

selectcount(*) from part_tab where c3 > date '1995-01-01'and c3 < date '1995-12-31';

+----------+
| count(*) |
+----------+
|   795181 |
+----------+
1 row in set (7.33 sec)

分區表的執行時間比普通表少70%。

 

4.     經過explain語句來分析執行狀況

mysql>explain select count(*) from part_tab where c3 > date '1995-01-01'and c3 < date '1995-12-31';

+----+-------------+----------+------+---------------+------+---------+------+---------+-------------+

| id |select_type | table    | type |possible_keys | key  | key_len | ref  | rows   | Extra       |

+----+-------------+----------+------+---------------+------+---------+------+---------+-------------+

|  1 | SIMPLE      | part_tab | ALL  | NULL          | NULL | NULL    | NULL | 7980796 | Using where |

+----+-------------+----------+------+---------------+------+---------+------+---------+-------------+

1 rowin set

 

mysql>explain select count(*) from no_part_tab where c3 > date '1995-01-01'and c3 < date '1995-12-31';

+----+-------------+-------------+------+---------------+------+---------+------+---------+-------------+

| id |select_type | table       | type |possible_keys | key  | key_len | ref  | rows   | Extra       |

+----+-------------+-------------+------+---------------+------+---------+------+---------+-------------+

|  1 | SIMPLE      | no_part_tab | ALL  | NULL          | NULL | NULL    | NULL | 8000206 | Using where |

+----+-------------+-------------+------+---------------+------+---------+------+---------+-------------+

1 rowin set

mysql >

分區表執行掃描了7980796行,而普通表則掃描了8000206行。

相關文章
相關標籤/搜索