1. 程式人生 > >Mysql分割槽表介紹

Mysql分割槽表介紹

分割槽:
分割槽的功能不是在儲存引擎層實現的。因此不只是InnoDB才支援分割槽。MyISAM、NDB都支援分割槽操作。

分割槽的過程是將一個表或者索引分解為多個更小、更可管理的部分。從邏輯上將,只有一個表或者索引,但是在物理上這個表或索引可能由數十個物理分割槽組成。
每個分割槽都是獨立的物件,可以獨自處理,也可以作為一個更大物件的一部分進行處理。

MySQL只支援水平分割槽,不支援垂直分割槽。
水平分割槽:將同一表中不同行的記錄分配到不同的物理檔案中。
垂直分割槽:將同一表中不同列的記錄分配到不同的物理檔案中。

MySQL資料庫的分割槽是區域性分割槽索引。一個分割槽中既存放了資料又存放了索引。而全域性分割槽索引指的是資料存放在各個分割槽中,但是所有資料的索引放在一個物件中。MySQL暫時還不支援全域性分割槽索引。

檢視當前資料庫是否啟用了分割槽功能:

> show plugins\G   partition狀態是ACTIVE表示可以支援分割槽。

檢視目前MySQL上有哪些分割槽表:

SELECT TABLE_SCHEMA, TABLE_NAME, PARTITION_NAME,PARTITION_METHOD,CREATE_TIME from `PARTITIONS` where PARTITION_NAME is not null ;

MySQL資料庫支援以下幾種型別的分割槽:
RANGE分割槽
LIST分割槽
HASH分割槽
KEY分割槽

如下就是建立分割槽的表的方式:

> create table t4 (
col1 int null,
col2 date null,
col3 int null,
col4 int null,
key (col3)
) engine=InnoDB
partition BY HASH (col3)
partitions 4;        -- 劃分成4個分割槽
-rw-rw---- 1 mariadb mariadb 98304 2016-08-07 09:59 t4#P#p0.ibd
-rw-rw---- 1 mariadb mariadb 98304 2016-08-07 09:59 t4#P#p1.ibd
-rw-rw----
1 mariadb mariadb 98304 2016-08-07 09:59 t4#P#p2.ibd -rw-rw---- 1 mariadb mariadb 98304 2016-08-07 09:59 t4#P#p3.ibd

分割槽型別:
1 RANGE分割槽:

> create table t1 (id int)
partition by range(id)(
partition p0 values less than (10),
partition p1 values less than (20));

當資料小於10的時候,插入p0分割槽。大於等於10小於20時候,插入p1分割槽。

> INSERT INTO t1 SELECT 12;
> INSERT INTO t1 SELECT 2;

表物理檔案變成了下面這種:

-rw-rw---- 1 mariadb mariadb 98304 2016-08-07 10:14 t1#P#p0.ibd
-rw-rw---- 1 mariadb mariadb 98304 2016-08-07 10:17 t1#P#p1.ibd

從表面上,看不出來到底插入到什麼分割槽中了,可以用下面的命令檢視:

> SELECT * from information_schema.PARTITIONS where table_schema=database() and table_name='t1'\G

***************************[ 1. row ]***************************
TABLE_CATALOG                 | def
TABLE_SCHEMA                  | hellodb
TABLE_NAME                    | t1
PARTITION_NAME                | p0        # 這裡能看到是插入到p0分割槽的
SUBPARTITION_NAME             | None
PARTITION_ORDINAL_POSITION    | 1
SUBPARTITION_ORDINAL_POSITION | None
PARTITION_METHOD              | RANGE       # 這裡看得出是range分割槽型別
SUBPARTITION_METHOD           | None
PARTITION_EXPRESSION          | id
SUBPARTITION_EXPRESSION       | None
PARTITION_DESCRIPTION         | 10
TABLE_ROWS                    | 1           # 這個反映了該分割槽(這裡是p0)記錄的行數量。
AVG_ROW_LENGTH                | 16384
DATA_LENGTH                   | 16384
MAX_DATA_LENGTH               | None
INDEX_LENGTH                  | 0
DATA_FREE                     | 0
CREATE_TIME                   | None
UPDATE_TIME                   | None
CHECK_TIME                    | None
CHECKSUM                      | None
PARTITION_COMMENT             | 
NODEGROUP                     | default
TABLESPACE_NAME               | None
***************************[ 2. row ]***************************
TABLE_CATALOG                 | def
TABLE_SCHEMA                  | hellodb
TABLE_NAME                    | t1
PARTITION_NAME                | p1        # 這裡能看到是插入到p1分割槽的
SUBPARTITION_NAME             | None
PARTITION_ORDINAL_POSITION    | 2
SUBPARTITION_ORDINAL_POSITION | None
PARTITION_METHOD              | RANGE
SUBPARTITION_METHOD           | None
PARTITION_EXPRESSION          | id
SUBPARTITION_EXPRESSION       | None
PARTITION_DESCRIPTION         | 20
TABLE_ROWS                    | 1
AVG_ROW_LENGTH                | 16384
DATA_LENGTH                   | 16384
MAX_DATA_LENGTH               | None
INDEX_LENGTH                  | 0
DATA_FREE                     | 0
CREATE_TIME                   | None
UPDATE_TIME                   | None
CHECK_TIME                    | None
CHECKSUM                      | None
PARTITION_COMMENT             | 
NODEGROUP                     | default
TABLESPACE_NAME               | None

INSERT INTO t1 SELECT 32; # 這個插入會報錯,因為我們上面定義的分割槽,並不包含這個區間。
對此,要允許插入大數的話,可以修改下表:
ALTER TABLE t1 add partition( partition p2 values less than (30)); 或者 ALTER TABLE t1 add partition( partition p2 values less than maxvalue );
這下我們插入大數值的話,也不會報錯了。

RANGE分割槽主要用於日期列的分割槽,例如對於銷售類的表,可以根據年來分割槽存放銷售記錄。如下面的分割槽表sales:

> CREATE TABLE sales (
money INT UNSIGNED NOT NULL,
`date` DATETIME
) ENGINE=INNODB
PARTITION BY RANGE (YEAR(DATE)) (
PARTITION p2008 VALUES LESS THAN (2009),
PARTITION p2009 VALUES LESS THAN (2010),
PARTITION p2010 VALUES LESS THAN (2011)
);

> INSERT INTO sales SELECT 2399,'2008-04-20';
> INSERT INTO sales SELECT 6569,'2009-01-25';
> INSERT INTO sales SELECT 2399,'2010-12-20';

這樣的話,不同年份的資料就插入到不同的分割槽中,便於對sales這張表進行管理。
如果要刪除2008年的資料,不需要執行delete from sales where date>=’2008-01-01’ and date<=’2008-12-31’; 只要刪除2008年資料所在的分割槽即可:

> alter table sales drop partition p2008;

分割槽的另一個好處是:
加快某些查詢,例如我們只要查詢2009年整年的銷售額,如下即可:

> explain partitions select * from sales where date >='2009-01-01' and date <='2009-12-31'\G
***************************[ 1. row ]***************************
id            | 1
select_type   | SIMPLE
table         | sales
partitions    | p2009    # 只去p2009這個分割槽去搜索
type          | ALL
possible_keys | None
key           | None
key_len       | None
ref           | None
rows          | 2
Extra         | Using where

最常用的就是range分割槽。
但是注意:如果分割槽鍵是timestamp型別的,則必須用UNIX_TIMESTAMP轉換下。如下例子:

ALTER TABLE `order_his_tmp` drop primary key, add primary key(id,order_time);   去掉原先的主鍵,加一個帶分割槽ID的主鍵。

ALTER TABLE `order_his_tmp` PARTITION BY RANGE (UNIX_TIMESTAMP (order_time)) ( 
 PARTITION  p201508  VALUES LESS THAN  (UNIX_TIMESTAMP('2015-09-01')) ,
 PARTITION  p201509  VALUES LESS THAN  (UNIX_TIMESTAMP('2015-10-01')) ,
 PARTITION  P201510  VALUES LESS THAN  (UNIX_TIMESTAMP('2015-11-01')) ,
 PARTITION  P201511  VALUES LESS THAN  (UNIX_TIMESTAMP('2015-12-01')) ,
 PARTITION  P201512  VALUES LESS THAN  (UNIX_TIMESTAMP('2016-01-01')) ,
 PARTITION  P201601  VALUES LESS THAN  (UNIX_TIMESTAMP('2016-02-01')) ,
 PARTITION  P201602  VALUES LESS THAN  (UNIX_TIMESTAMP('2016-03-01')) );

對於分割槽鍵是DATETIME的,要用TO_DAYS()函式操作,如下例子:

> CREATE TABLE sales(
money int unsigned not null,
date datetime)
partition by range (TO_DAYS(date)) (
partition p201001 values less than (TO_DAYS('2010-02-01')), 
partition p201002 values less than (TO_DAYS('2010-03-01')), 
partition p201003 values less than (TO_DAYS('2010-04-01'))
);

2 LIST分割槽【不多見】:
和range分割槽類似,只是分割槽列的值是雜湊的,而非連續的。

> CREATE TABLE t (
a INT,
b INT) ENGINE INNODB
PARTITION BY LIST(b) (
PARTITION p0 VALUES IN (1,3,5,7,9),
PARTITION p1 VALUES IN (2,4,6,8)
);

注意:list分割槽中使用的是VALUES IN 這種格式。

> insert into t select 3,2;
> insert into t select 2,12;  執行這行插入語句會報錯,因為按照LIST(b)劃分的話,12不在上述的LIST裡面。
> insert into t select 3,4;  執行這行插入語句會報錯,因為按照LIST(b)劃分的話,4不在上述的LIST裡面。
> insert into t select 3,5;

> SELECT table_name,partition_name,table_rows from information_schema.Partitions where table_name='t' and table_schema=DATABASE()\G

結果如下:

***************************[ 1. row ]***************************
table_name     | t
partition_name | p0
table_rows     | 1
***************************[ 2. row ]***************************
table_name     | t
partition_name | p1
table_rows     | 2   表示p1分割槽有2行資料

注意:
InnoDB和MyISAM在遇到一次性插入多條資料中出現分割槽未定義錯誤的時候處理方式是不同的。
InnoDB會把整個SQL語句當做一個事務,只要有錯誤,就完全不執行。而MyISAM則會將錯誤之前的sql都執行成功。

3 HASH分割槽:
HASH分割槽的目的是將資料均勻地分佈到預先定義的各個分割槽中,保證各分割槽的資料數量大致都是一樣的。
在RANGE和LIST分割槽中,必須明確指定一個給定的列值或列值集合應該儲存在哪個分割槽中。在HASH分割槽中,MySQL自動完成這些工作,用於所要做的只是基於將要進行雜湊分割槽的列值指定一個列值或表示式,以及指定備份去的表將要被分割成的分割槽數量。
要使用HASH分割槽來分割一個表,要在CREATE TABLE語句上新增一個 PARTITION BY HASH(expr) 子句,其中expr是一個返回一個整數的表示式。它可以僅僅是欄位型別為MySQL整型的列名。
此外,使用者可以自定義分割槽的數量,只要加上引數PARTITIONS xxx即可。如下:

> create table t_hash (
a int,
b datetime
) engine innodb
PARTITION BY HASH (YEAR(b))
PARTITIONS 4;
> INSERT INTO t_hash VALUES (6,'2013-03-11 12:21:22');

上面這條插入的話,實際上要執行MOD(2013,4)取餘數,得出這行資料存放在哪個分割槽中。

> SELECT table_name,partition_name,table_rows FROM information_schema.`PARTITIONS` WHERE table_schema=DATABASE() AND table_name='t_hash' ;
結果如下:
+------------+----------------+------------+
| table_name | partition_name | table_rows |
+------------+----------------+------------+
| t_hash     | p0             |          0 |  
| t_hash     | p1             |          1 |  # 可以看到p1插入了4條資料,因為2013年除以4,餘數是1。因此2013年都資料都落在p1分割槽
| t_hash     | p2             |          0 |
| t_hash     | p3             |          0 |
+------------+----------------+------------+

4 LINEAR HASH分割槽:(線性hash)
mysql還支援這種複雜的分割槽演算法。語法和HASH分割槽類似,只是將關鍵字HASH改成了LINEAR HASH。

如下:

> CREATE TABLE t_l_hash (
a INT,
b DATETIME
) ENGINE INNODB
PARTITION BY LINEAR HASH(YEAR(b))
PARTITIONS 4;

取大於分割槽數量4的下一個2的冪值V,V=POWER(2,CEILING(LOG(2,num)))=4
所在分割槽N=YEAR(‘2010-04-01’)&(V-1)=2.
LINEAR HASH分割槽的
優點:
增加、刪除、合併和拆分分割槽將變得更加快捷,有利於處理含有大量資料的表。
缺點:
與使用HASH分割槽得到的資料分佈相比,各個分割槽間資料的分佈可能不大均衡。

> INSERT INTO t_l_hash VALUE (2,'2014-04-23 12:23:33');

> SELECT table_name,partition_name,table_rows
FROM information_schema.`PARTITIONS`
WHERE table_schema=DATABASE() AND table_name='t_l_hash'\G

結果如下:

***************************[ 1. row ]***************************
table_name     | t_l_hash
partition_name | p0
table_rows     | 1
***************************[ 2. row ]***************************
table_name     | t_l_hash
partition_name | p1
table_rows     | 0
***************************[ 3. row ]***************************
table_name     | t_l_hash
partition_name | p2
table_rows     | 1
***************************[ 4. row ]***************************
table_name     | t_l_hash
partition_name | p3
table_rows     | 0

5 KEY分割槽:
和HASH分割槽類似,不同之處在於HASH分割槽使用使用者定義的函式進行分割槽,KEY分割槽使用MySQL資料庫提供的函式進行分割槽。
對於NDB Cluster引擎,MySQL資料庫使用MD5函式來分割槽;對於其他引擎,使用MySQL內部的雜湊函式來分割槽。

> CREATE TABLE t_key (
a INT,
b DATETIME
) ENGINE INNODB
PARTITION BY KEY(b)
PARTITIONS 4 ;

6 COLUMNS分割槽【很常用】:
前面的幾種分割槽都是有條件限制的。條件是:必須是整型,如果不是整型,那麼也必須是可以通過函式轉換為整型的,如YEAR()、TO_DAYS()、MONTH()等函式。
MySQL5.5版本開始支援的COLUMNS分割槽,可視為RANGE分割槽和LIST分割槽的一種進化。
COLUMNS分割槽看直接使用非整型的資料進行分割槽,分割槽根據型別直接比較而得,不需要轉換為整型。
此外,COLUMNS分割槽可以對多個列的值進行分割槽。
COLUMNS分割槽支援以下的資料型別:
1 所有的整型型別
支援:INT、SMALLINT、TINYINT、BIGINT。不支援:FLOAT和DECIMAL
2 日期型別 【常用】
支援 DATE、DATETIME
3 字串型別
支援 CAHR、VARCHAR、BINARY、VARBINARY。不支援BLOB和TEXT

> CREATE TABLE t_columns_range (
a INT,
b DATETIME
)ENGINE INNODB
PARTITION BY  RANGE COLUMNS (B) (
PARTITION p0 VALUES LESS THAN ('2009-01-01'),
PARTITION p1 VALUES LESS THAN ('2010-01-01')
);

注意和range分割槽的SQL語句差別!!(分割槽範圍裡不用函式處理列了)

對於現有的表改成分割槽表:

ALTER TABLE `tb_detail` drop primary key ,add primary key (id, bill_date);

ALTER TABLE `tb_detail` PARTITION BY RANGE COLUMNS (bill_date)   (   
PARTITION  p201509  VALUES LESS THAN  ('2015-10-01') ,   
PARTITION  P201510  VALUES LESS THAN  ('2015-11-01') ,
PARTITION  P201511  VALUES LESS THAN  ('2015-12-01') ,
PARTITION  P201512  VALUES LESS THAN  ('2016-01-01') ,
PARTITION  P201601  VALUES LESS THAN  ('2016-02-01') ,
PARTITION  P201602  VALUES LESS THAN  ('2016-03-01') ,
PARTITION  P201603  VALUES LESS THAN  ('2016-04-01') ,
PARTITION  P201604  VALUES LESS THAN  ('2016-05-01') );

對於RANGE COLUMNS分割槽,可以使用多個列進行分割槽,如:

> CREATE TABLE rcx (
a INT,
b INT,
c CHAR(3),
d INT
)ENGINE INNODB
PARTITION BY  RANGE COLUMNS (a,b,c) (
PARTITION p0 VALUES LESS THAN (5,10,'ggg'),
PARTITION p1 VALUES LESS THAN (10,20,'mmm'),
PARTITION p2 VALUES LESS THAN (15,30,'sss'),
PARTITION p3 VALUES LESS THAN (MAXVALUE,MAXVALUE,MAXVALUE)
);

MySQL5.5開始支援COLUMNS分割槽。對於之前的RANGE和LIST分割槽。使用者可以用RANGE COLUMNS和LIST COLUMNS分割槽進行很好的代替。

手工新增分割槽:

CREATE TABLE `t10` (
 `a` int(11) NOT NULL AUTO_INCREMENT,
 `b` int(11) DEFAULT NULL,
 PRIMARY KEY (`a`)
) ENGINE=InnoDB AUTO_INCREMENT=121 DEFAULT CHARSET=utf8
PARTITION BY RANGE  COLUMNS(a)
(PARTITION p0 VALUES LESS THAN (10) ENGINE = InnoDB,
PARTITION p1 VALUES LESS THAN (20) ENGINE = InnoDB,
PARTITION p2 VALUES LESS THAN (30) ENGINE = InnoDB,
PARTITION p3 VALUES LESS THAN (40) ENGINE = InnoDB,
PARTITION p4 VALUES LESS THAN (50) ENGINE = InnoDB,
PARTITION p5 VALUES LESS THAN (60) ENGINE = InnoDB,
PARTITION p6 VALUES LESS THAN (70) ENGINE = InnoDB,
PARTITION p7 VALUES LESS THAN (80) ENGINE = InnoDB,
PARTITION p8 VALUES LESS THAN (90) ENGINE = InnoDB,
PARTITION p9 VALUES LESS THAN (100) ENGINE = InnoDB );  ---> 注意這裡最後一個分割槽範圍沒有像上面其他案例那樣寫死

後期可以使用 ALTER TABLE t10 ADD PARTITION (PARTITION p10 VALUES LESS THAN (110)); 這樣就可以加一個分割槽了。

子分割槽:
子分割槽(subpartitioning)是在分割槽的基礎上在進行分割槽,有時也稱這種分割槽為複合分割槽(composite partitioning)。
MySQL資料庫允許在RANGE和LIST分割槽上再進行HASH或KEY的子分割槽。如:

> CREATE TABLE ts (
a INT,
b DATE
) ENGINE=INNODB
PARTITION BY RANGE(YEAR(b))
SUBPARTITION BY HASH(TO_DAYS(b))
SUBPARTITIONS 2 (
PARTITION p0 VALUES LESS THAN (1990),
PARTITION p1 VALUES LESS THAN (2000),
PARTITION p2 VALUES LESS THAN MAXVALUE);

在物理檔案上表示形式如下:

-rw-rw---- 1 mariadb mariadb   711 2016-08-07 19:28 ts.frm
-rw-rw---- 1 mariadb mariadb   108 2016-08-07 19:28 ts.par
-rw-rw---- 1 mariadb mariadb 98304 2016-08-07 19:28 ts#P#p0#SP#p0sp0.ibd
-rw-rw---- 1 mariadb mariadb 98304 2016-08-07 19:28 ts#P#p0#SP#p0sp1.ibd
-rw-rw---- 1 mariadb mariadb 98304 2016-08-07 19:28 ts#P#p1#SP#p1sp0.ibd
-rw-rw---- 1 mariadb mariadb 98304 2016-08-07 19:28 ts#P#p1#SP#p1sp1.ibd
-rw-rw---- 1 mariadb mariadb 98304 2016-08-07 19:28 ts#P#p2#SP#p2sp0.ibd
-rw-rw---- 1 mariadb mariadb 98304 2016-08-07 19:28 ts#P#p2#SP#p2sp1.ibd

先進行range分割槽(p0\p1\p2),再進行hash分割槽(sp0\sp1)。(合計共3*2=6個分割槽),上面物理檔案上面也能看出來是6個分割槽。

子分割槽的建立需要注意下面問題:
1、每個子分割槽的數量必須相同。
2、要在一個分割槽表的任何分割槽上使用SUBPARTITION來明確定義任何子分割槽,就必須定義所有的子分割槽。
3、每個SUBPARTITION子句必須包括子分割槽的一個名字。
4、子分割槽的名字必須是唯一的。

子分割槽可以用於特別大的表,在多個磁碟間分別分配資料和索引。
如下為6個磁碟的分割槽例項(InnoDB引擎):

> CREATE TABLE ts (
a INT,
b DATE)ENGINE INNODB
PARTITION BY RANGE(YEAR(b))
SUBPARTITION BY HASH(TO_DAYS(b)) (
PARTITION p0 VALUES LESS THAN (2000) (
SUBPARTITION s0
DATA DIRECTORY = '/disk0/data'
INDEX DIRECTORY = '/disk0/idx',
SUBPARTITION s1
DATA DIRECTORY = '/disk1/data'
INDEX DIRECTORY = '/disk1/idx'
),
PARTITION p1 VALUES LESS THAN (2010) (
SUBPARTITION s2
DATA DIRECTORY = '/disk2/data'
INDEX DIRECTORY = '/disk2/idx',
SUBPARTITION s3
DATA DIRECTORY = '/disk3/data'
INDEX DIRECTORY = '/disk3/idx'
),
PARTITION p2 VALUES LESS THAN MAXVALUE (
SUBPARTITION s4
DATA DIRECTORY = '/disk4/data'
INDEX DIRECTORY = '/disk4/idx',
SUBPARTITION s5
DATA DIRECTORY = '/disk5/data'
INDEX DIRECTORY = '/disk5/idx'
)
);

分割槽中的NULL值:
MySQL允許對NULL值做分割槽。但是處理的方法與其他資料庫完全不同。
MySQL資料庫的分割槽總是視NULL值小於任何的一個非NULL值,這和MySQL資料庫中處理NULL值的ORDER BY操作是一樣的。因此對於不同的分割槽型別,MySQL資料庫對於NULL值的處理也是各不相同。

1、RANGE分割槽中使用NULL值:

> CREATE table t_range(
     a int,
     b int)
     partition by range(b) (
     partition p0 VALUES less than (10),
     partition p1 VALUES less than (20),
     partition p2 values less than maxvalue);

   > insert into t_range select 1,1;
   > insert into t_range select 2,null;

   > SELECT table_name,partition_name,table_rows
FROM information_schema.`PARTITIONS`
WHERE table_schema=DATABASE() AND table_name='t_range';

結果如下:

+------------+----------------+------------+
| table_name | partition_name | table_rows |
+------------+----------------+------------+
| t_range    | p0             |          2 |
| t_range    | p1             |          0 |
| t_range    | p2             |          0 |
+------------+----------------+------------+

可以看到插入的資料都放到了p0分割槽。
也就是說在RANGE分割槽下,NULL值會放入最左邊的分割槽中。
另外,如果刪除了p0分割槽,刪除的將是小於10的記錄和NULL值的記錄,這點非常重要。

> alter table t_range drop partition p0;
> SELECT * from t_range;  可以看到下圖的表已經為空值了
+-----+-----+
| a   | b   |
|-----+-----|
+-----+-----+

2、LIST分割槽下使用NULL值,必須顯式的指出哪個分割槽中放入NULL值,否則會報錯。
如下寫法才能允許插入NULL值。

> CREATE table t_list (
a int,
b int)
partition by list(b) (
partition p0 values in (1,3,5,7,9,NULL),    # 注意必須顯式的指出NULL插入到那個分割槽才行
partition p1 VALUES in (2,4,6,8,10));

> INSERT INTO t_list SELECT 1,4;
> INSERT INTO t_list SELECT 3,null;

> SELECT table_name,partition_name,table_rows
IFROM information_schema.`PARTITIONS`
WHERE table_schema=DATABASE() AND table_name='t_list'\G

結果如下:

***************************[ 1. row ]***************************
table_name     | t_list
partition_name | p0
table_rows     | 1
***************************[ 2. row ]***************************
table_name     | t_list
partition_name | p1
table_rows     | 1

3、HASH和KEY分割槽對於NULL的處理方式和RANGE分割槽、LIST分割槽不一樣。
任何分割槽函式都會將含有NULL值的記錄返回為0。【返回0的說明是存放在第一個分割槽中】

> create table t_hash (
a int,
b int ) engine=innodb
partition by hash(b)
partitions 4;

> INSERT INTO t_hash SELECT 3,null;
> INSERT INTO t_hash SELECT 3,6778;

 > SELECT table_name,partition_name,table_rows
FROM information_schema.`PARTITIONS`
WHERE table_schema=DATABASE() AND table_name='t_hash'\G

結果如下:

***************************[ 1. row ]***************************
table_name     | t_hash
partition_name | p0
table_rows     | 1
***************************[ 2. row ]***************************
table_name     | t_hash
partition_name | p1
table_rows     | 0
***************************[ 3. row ]***************************
table_name     | t_hash
partition_name | p2
table_rows     | 1
***************************[ 4. row ]***************************
table_name     | t_hash
partition_name | p3
table_rows     | 0

在表和分割槽之間交換資料:
mysql5.6開始支援 ALTER TABLE … EXCHANGE PARTITION 語法。該語句允許分割槽或子分割槽的資料與另一個非分割槽的表中的資料進行交換。
如果非分割槽表中的資料為空,那麼相當於分割槽中的資料移動到非分割槽表中。
若分割槽表中的資料為空,則相當於將外部表中的資料匯入到分割槽中。

要使用ALTER TABLE … EXCHANGE語句,必須滿足下面的條件:
1 要交換的表需要和分割槽表有相同的表結構,但是不能有分割槽。
2 在非分割槽表中的資料必須在交換的分割槽定義內。
3 被交換的表中不能含有外來鍵,或者其他的表含有對該表的外來鍵引用。
4 使用者除了需要alter、insert、create許可權外,還需要drop的許可權。
此外,有2個小的細節要注意:
1、使用該語句時,不會觸發交換表和被交換表上的觸發器。
2、AUTO_INCREMENT列將被重置。

例子:
建立一個含有RANGE分割槽的表e,並填充資料:

> CREATE TABLE e (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30)
)
PARTITION BY RANGE (id) (
PARTITION p0 VALUES LESS THAN (50),
PARTITION p1 VALUES LESS THAN (100),
PARTITION p2 VALUES LESS THAN (150),
PARTITION p3 VALUES LESS THAN (MAXVALUE)
);

> INSERT INTO e VALUES
(33,'zhang','san'),
(156,'jim','ling'),
(1114,'wang','wu'),
(1454,'li','si');

然後建立交換表e2。結構和表e一樣,但是表e2中不含有分割槽。

> CREATE TABLE e2 (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30)
); 

或者create table e2 like e; alter table e2 remove partitioning; 即可建立相同表結構的不帶分割槽引數的表e2

觀察分割槽表的中的資料:

> SELECT partition_NAME,TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='e';
+------------------+--------------+
| partition_NAME   |   TABLE_ROWS |
|------------------+--------------|
| p0               |            1 |
| p1               |            0 |
| p2               |            0 |
| p3               |            3 |
+------------------+--------------+

> SELECT partition_NAME,TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='e2';  可以看到e2表暫時是空的

使用alter table命令交換資料:

> ALTER TABLE e exchange PARTITION p0 WITH TABLE e2;  將表e的分割槽p0中的資料移動到表e2中。

再次查看錶e中分割槽的資料,可以看到p0中已經沒有資料了。

> SELECT partition_NAME,TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='e';
+------------------+--------------+
| partition_NAME   |   TABLE_ROWS |
|------------------+--------------|
| p0               |            0 |
| p1               |            0 |
| p2               |            0 |
| p3               |            3 |
+------------------+--------------+

> SELECT * from e2;   檢視e2表,可以看到多了一條資料,就是從e交換而來的。
+------+---------+---------+
|   id | fname   | lname   |
|------+---------+---------|
|   33 | zhang   | san     |
+------+---------+---------+

相關推薦

Mysql分割槽介紹

分割槽: 分割槽的功能不是在儲存引擎層實現的。因此不只是InnoDB才支援分割槽。MyISAM、NDB都支援分割槽操作。 分割槽的過程是將一個表或者索引分解為多個更小、更可管理的部分。從邏輯上將,只有一個表或者索引,但是在物理上這個表或索引可能由數十個物理分

2.ORACLE分割槽遷移MySQL分割槽

介紹 由於MySQL沒有類似於ORACLE間隔分割槽類似的功能,所以遷移分割槽表的時候工作量較大,下面就把常用到的一些工具指令碼及操作過程列在下面。 操作 1 修改分割槽表定義 ORACLE增加了間隔分割槽功能,可以在資料插入的時候自動新增分割槽,但是MySQL就不具備這個功

網際網路公司為啥不使用mysql分割槽

解決什麼問題? 回答:當mysql單表的資料庫過大時,資料庫的訪問速度會下降,“資料量大”問題的常見解決方案是“水平切分”。   mysql常見的水平切分方式有哪些? 回答:分庫分表,分割槽表   什麼是mysql的分庫分表? 回答:把一個很大的庫(表

mysql 分割槽 range分割槽

首先呢我們來看下怎麼建立一個分割槽表 在上節課的時候 我們也說過 在分割槽的時候 如果分割槽欄位中有主鍵或者唯一索引的列,那麼多有主鍵列和唯一索引列都必須包含進來。 1 ,按照年齡的範圍 create table staff_r12( id int not null auto_inc

Hive內部、外部分割槽介紹

1.內部表: hive>create table tt (name string , age string); //此時會在hdfs的/user/hive/warehouse/目錄下新建一個tt表的資料存放地 hive>load data inpath '/input/data' into tab

MySQL分割槽、HBase 融合祕術

導讀 時常都會有人問MySQL分割槽表要如何使用,MySQL分割槽表的和Oracle的差遠了,該不該用MySQL分割槽表。 囉哩八嗦 其實該不該用,我也不能給予很好的建議。還是那句話,覺得適合自己才是最好的。覺得自己可以搞定分割槽表那就用。 我多慮了 好很好的使用分

MySQL分割槽(總結)

4.13 只有RANG和LIST分割槽能進行子分割槽。HASH和KEY分割槽不能進行子分割槽。 4.14 分割槽表不支援Key caches。 SQL程式碼 mysql> SET GLOBAL keycache1.key_buffer_size=128*1024;   Query OK, 0 rows

第17章 Mysql分割槽,已有變更分割槽

實際對比測試的時候,沒有發現查詢效能有明顯提升,有待實際例子支撐。 檢視是否支援: show variables like '%partition%' RANGE分割槽:http://www.cnblogs.com/chenmh/p/5627912.html LIST分割

Mysql --分割槽(7)Key分割槽

Key分割槽 按照Key進行分割槽非常類似於按照Hash進行分割槽,只不過Hash分割槽允許使用使用者自定義的表示式,而Key分割槽不允許使用使用者自定義的表示式,需要使用MySQL伺服器提供的HASH函式;同時Hash分割槽只支援整數分割槽,而Key分割槽支

Mysql分割槽使用的一些限制和需要注意的地方

mysql分割槽策略都基於兩個非常重要的假設:查詢都能夠過濾(prunning)掉很多額外的分割槽、分割槽本身並不會帶來很多額外的代價。而事實證明,這兩個假設在某些場景下會有問題。下面介紹一些可能會遇到的問題。 NULL位會使分割槽過濾無效   關於分割槽表一個容易讓人

Mysql分割槽、合併查詢比較

合併表:   ---- 執行範圍查詢時,需要在每一個子表上各執行一次,這比直接訪問單個表的效能差很多,而且子表越多,效能越糟   ----全表掃描和普通表的全表掃描速度相同   ----在合併表上做唯

MySQL之mysqldump鎖介紹

https http ref dump 地址 into ons .cn mysqldump 參考地址:https://www.cnblogs.com/digdeep/p/4898622.htmlhttp://imysql.cn/2008_10_24_deep_into_my

mysql分割槽、主從複製

1.分割槽的工作原理 對使用者而言,分割槽表是一個獨立的邏輯表,但mysql底層將其分成了多個物理子表,每一個分割槽都是一個獨立的子檔案; 分割槽不需要改動原先的sql語句。 建立表時使用partition by子句定義每個分割槽存放的資料,執行查詢時,mysql優化器會過濾那些沒有我們

MySQL技術內幕 InnoDB儲存引擎:分割槽

一、MySQL分割槽表介紹 分割槽是一種表的設計模式,正確的分割槽可以極大地提升資料庫的查詢效率,完成更高質量的SQL程式設計。但是如果錯誤地使用分割槽,那麼分割槽可能帶來毀滅性的的結果。 分割槽功能並不是在儲存引擎層完成的,因此不只有InnoDB儲存引擎支援分割槽,常見的儲存引

MySQL技術&分割槽技術

一、分表技術 1、說明 說明:當一張表資料巨大時,不管如何優化,查詢也會相當慢 解決:1-增加查詢快取,2-使用分表技術 2、實現分表的方法 水平分表:手動建立多張表,通過PHP演算法判斷實現讀寫 垂直分表:將表字段拆分到其他表中 3、水平分表 水平分表圖示:

MySQL 合併分割槽

合併表 create table mtable1(data int not null primary key) engine=myisam; create table mtable2(data int not null primary key) engine=myis

MySQL 分割槽分庫分簡介

1.Mysql分割槽:     (1) 是什麼:如一張表的資料量太大,那麼myd,myi就會變的很大,查詢資料就會變的很慢,這個時候我們可以利用mysql的分割槽功能,在物理上將這一張表對應的三個檔案,分割成許多個小塊,這樣呢,我們查詢一條資料時,就不用全部查找了,只要知道這條資料在哪一塊,然後在那一塊找就

MySQL分割槽

主從複製 - 讀寫分離要解決的是資料庫併發訪問壓力; 分表和分割槽解決的是單表資料量大時的SQL效能壓力,另外分表也能一定程度上提高併發; 1. 什麼是分表、分割槽?分表和分割槽是不同層次的概念: 分表: 分表是開發人員的物理設計,目的是:在單表有大資料量的情況下保證SQL執行效能,也能提高併發。 我

一個MySQL 5.7分割槽效能下降的案例分析與排查

作者介紹 姜宇祥,2012年加入攜程,10年資料庫核心程式碼開發經驗,相關開發涉及達夢、MySQL資料庫。現致力於攜程MySQL的底層研發,為特殊問題定位和處理提供技術支援。 前言:希望通過本文,使MySQL5.7.18的使用者知曉分割槽表使用中存在的陷阱,避免在該版本上繼續踩坑。同時通過對原始碼的

MySQL 5.7 分割槽效能下降的案例分析

告知MySQL5.7.18的使用者分割槽表使用中存在的陷阱,避免在該版本上繼續踩坑。同時通過對原始碼的講解,升級MySQL5.7.18時分割槽表效能下降的根本原因,向MySQL原始碼愛好者展示分割槽表實現中鎖的運用。 問題描述 MySQL 5.7版本中,效能相關的改進非常多。包括臨時表相關的效能改進,連線