MySQL分區表創建,查看,維護


一、       mysql分區簡介

數據庫分區

數據庫分區是一種物理數據庫設計技術。雖然分區技術可以實現很多效果,但其主要目的是為了在特定的SQL操作中減少數據讀寫的總量以縮減sql語句的響應時間,同時對於應用來說分區完全是透明的。

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

 

水平分區(HorizontalPartitioning)

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

 

垂直分區(VerticalPartitioning)

這種分區方式一般來說是通過對表的垂直划分來減少目標表的寬度,使某些特定的列被划分到特定的分區,每個分區都包含了其中的列所對應所有行。
可以用  showvariables like '%partition%';

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

分區的作用:數據庫性能的提升和簡化數據管理

在掃描操作中,mysql優化器只掃描保護數據的那個分區以減少掃描范圍獲得性能的提高。

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

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

二、   mysql分區類型

根據所使用的不同分區規則可以分成幾大分區類型。

RANGE 分區:

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

LIST 分區:

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

HASH分區:

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

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

復合分區:

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

三、mysql分區表常用操作示例

以部門員工表為例子:

1)       創建range分區

create table emp
(empno varchar(20) not null ,
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
);

--以員工工資為依據做范圍分區。

create table emp
(empno varchar(20) not null ,
empname varchar(20),
deptno int,
birthdate date not null,
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分區

create table emp
(empno  varchar(20) not null ,
empname varchar(20),
deptno  int,
birthdate date not null,
salary int
)
partition by list(deptno)
(
partition p1 values in  (10),
partition p2 values in  (20),
partition p3 values  in  (30)
);
--以部門作為分區依據,每個部門做一分區。

3)       創建hash分區

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

create table emp
(empno varchar(20) not null ,
empname varchar(20),
deptno int,
birthdate date not null,
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分區只采用一個或多個 列名的一個列表。

create table emp
(empno varchar(20) not null ,
empname varchar(20),
deptno int,
birthdate date not null,
salary int
)
partition by key(birthdate)
partitions 4;

5)       創建復合分區

--range - hash(范圍哈希)復合分區
create table emp
(empno varchar(20) not null ,
empname varchar(20),
deptno int,
birthdate date not null,
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復合分區
create table emp
(empno varchar(20) not null ,
empname varchar(20),
deptno int,
birthdate date not null,
salary int
)
partition by range(salary)
subpartition by key(birthdate)
subpartitions 3
(
partition p1 values less than (2000),
partition p2 values less than maxvalue
);

--list - hash復合分區
CREATE TABLE emp (
empno varchar(20) NOT NULL,
empname varchar(20) ,
deptno int,
birthdate date NOT NULL,
salary int
)
PARTITION BY list (deptno)
subpartition by hash(year(birthdate))
subpartitions 3
(
PARTITION p1 VALUES in  (10),
PARTITION p2 VALUES in  (20)
)
;

--list - key 復合分區
CREATE TABLE empk (
empno varchar(20) NOT NULL,
empname varchar(20) ,
deptno int,
birthdate date NOT NULL,
salary int
)
PARTITION BY list (deptno)
subpartition by key(birthdate)
subpartitions 3
(
PARTITION p1 VALUES in  (10),
PARTITION p2 VALUES in  (20)
)
;

6)       分區表的管理操作

刪除分區:
alter table emp drop partition p1;
不可以刪除hash或者key分區。
一次性刪除多個分區,alter table emp drop partition p1,p2;

增加分區:
alter table emp add partition (partition p3 values less than (4000));
alter table empl add partition (partition p3 values in (40));

分解分區:
Reorganizepartition關鍵字可以對表的部分分區或全部分區進行修改,並且不會丟失數據。分解前后分區的整體范圍應該一致。
alter table te
reorganize partition p1 into
(
partition p1 values less than (100),
partition p3 values less than (1000)
); ----不會丟失數據

 
合並分區:

Merge分區:把2個分區合並為一個。
alter table te
reorganize partition p1,p3 into
(partition p1 values less than (1000));
----不會丟失數據

重新定義hash分區表:
Alter table emp partition by hash(salary)partitions 7;
----不會丟失數據

重新定義range分區表:
Alter table emp partitionbyrange(salary)
(
partition p1 values less than (2000),
partition p2 values less than (4000)
); ----不會丟失數據

刪除表的所有分區:
Alter table emp removepartitioning;--不會丟失數據

 
重建分區:
這和先刪除保存在分區中的所有記錄,然后重新插入它們,具有同樣的效果。它可用於整理分區碎片。
ALTER TABLE emp rebuild partitionp1,p2;

 

優化分區:
如果從分區中刪除了大量的行,或者對一個帶有可變長度的行(也就是說,有VARCHAR,BLOB,或TEXT類型的列)作了許多修改,可以使用“ALTER TABLE ... OPTIMIZE PARTITION”來收回沒有使用的空間,並整理分區數據文件的碎片。
ALTER TABLE emp optimize partition p1,p2;

 
分析分區:
讀取並保存分區的鍵分布。
ALTER TABLE emp analyze partition p1,p2;

 
修補分區:
修補被破壞的分區。
ALTER TABLE emp repairpartition p1,p2;

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

ALTER TABLE emp CHECK partition p1,p2;

這個命令可以告訴你表emp的分區p1,p2中的數據或索引是否已經被破壞。如果發生了這種情況,使用“ALTER TABLE ... REPAIR PARTITION”來修補該分區。

【mysql分區表的局限性】

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

CREATE TABLE emptt (
empno varchar(20) NOT NULL  ,
empname varchar(20),
deptno int,
birthdate date NOT NULL,
salary int ,
primary key (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;

CREATE TABLE emptt (
empno varchar(20) NOT NULL  ,
empname varchar(20) ,
deptno int(11),
birthdate date NOT NULL,
salary int(11) ,
primary key (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.      臨時表不能被分區

四、   獲取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語句
--通過此語句來顯示掃描哪些分區,及他們是如何使用的.

五、 分區表性能比較

--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';
--1 row in set (2.62 sec)

--查詢普通表:
selectcount(*) from part_tab where c3 > date '1995-01-01'and c3 < date '1995-12-31';
--1 row in set (7.33 sec)
-- 分區表的執行時間比普通表少70%。


--4.     通過explain語句來分析執行情況
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

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

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

 

 

ref :https://www.cnblogs.com/pejsidney/p/10074980.html

 


免責聲明!

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



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