查看分區數據量,查看全庫數據量
USE information_schema;
SELECT PARTITION_NAME,TABLE_ROWS
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_NAME = 'sale_data';
SELECT table_name,table_rows FROM TABLES
WHERE TABLE_SCHEMA = 'db_name'
ORDER BY table_rows DESC
;
http://my.oschina.net/ydsakyclguozi/blog/393583
一、什么是表分區
通俗地講表分區是將一大表,根據條件分割成若干個小表。mysql5.1開始支持數據表分區了。
如:某用戶表的記錄超過了600萬條,那么就可以根據入庫日期將表分區,也可以根據所在地將表分區。當然也可根據其他的條件分區。
二、為什么要對表進行分區
為了改善大型表以及具有各種訪問模式的表的可伸縮性,可管理性和提高數據庫效率。
分區的一些優點包括:
1)、與單個磁盤或文件系統分區相比,可以存儲更多的數據。
2)、對於那些已經失去保存意義的數據,通常可以通過刪除與那些數據有關的分區,很容易地刪除那些數據。相反地,在某些情況下,添加新數據的過程又可以通過為那些新數據專門增加一個新的分區,來很方便地實現。通常和分區有關的其他優點包括下面列出的這些。MySQL分區中的這些功能目前還沒有實現,但是在我們的優先級列表中,具有高的優先級;我們希望在5.1的生產版本中,能包括這些功能。
3)、一些查詢可以得到極大的優化,這主要是借助於滿足一個給定WHERE語句的數據可以只保存在一個或多個分區內,這樣在查找時就不用查找其他剩余的分區。因為分區可以在創建了分區表后進行修改,所以在第一次配置分區方案時還不曾這么做時,可以重新組織數據,來提高那些常用查詢的效率。
4)、涉及到例如SUM()和COUNT()這樣聚合函數的查詢,可以很容易地進行並行處理。這種查詢的一個簡單例子如 “SELECT salesperson_id, COUNT (orders) as order_total FROM sales GROUP BY salesperson_id;”。通過“並行”,這意味着該查詢可以在每個分區上同時進行,最終結果只需通過總計所有分區得到的結果。
5)、通過跨多個磁盤來分散數據查詢,來獲得更大的查詢吞吐量。
三、分區類型
· RANGE分區:基於屬於一個給定連續區間的列值,把多行分配給分區。
· LIST分區:類似於按RANGE分區,區別在於LIST分區是基於列值匹配一個離散值集合中的某個值來進行選擇。
· HASH分區:基於用戶定義的表達式的返回值來進行選擇的分區,該表達式使用將要插入到表中的這些行的列值進行計算。這個函數可以包含MySQL 中有效的、產生非負整數值的任何表達式。
· KEY分區:類似於按HASH分區,區別在於KEY分區只支持計算一列或多列,且MySQL 服務器提供其自身的哈希函數。必須有一列或多列包含整數值。
1.RANGE分區
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(
30
),
lname VARCHAR(
30
),
hired DATE NOT NULL DEFAULT
'1970-01-01'
,
separated DATE NOT NULL DEFAULT
'9999-12-31'
,
job_code INT NOT NULL,
store_id INT NOT NULL
)
partition BY RANGE (store_id) (
partition p0 VALUES LESS THAN (
6
),
partition p1 VALUES LESS THAN (
11
),
partition p2 VALUES LESS THAN (
16
),
partition p3 VALUES LESS THAN (
21
)
);
|
對於包含數據(72, 'Michael', 'Widenius', '1998-06-25', NULL, 13)的一個新行,可以很容易地確定它將插入到p2分區中,但是如果增加了一個編號為第21的商店,將會發生什么呢?在這種方案下,由於沒有規則把store_id大於20的商店包含在內,服務器將不知道把該行保存在何處,將會導致錯誤。 要避免這種錯誤,可以通過在CREATE TABLE語句中使用一個“catchall” VALUES LESS THAN子句,該子句提供給所有大於明確指定的最高值的值:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(
30
),
lname VARCHAR(
30
),
hired DATE NOT NULL DEFAULT
'1970-01-01'
,
separated DATE NOT NULL DEFAULT
'9999-12-31'
,
job_code INT NOT NULL,
store_id INT NOT NULL
)
PARTITION BY RANGE (store_id) (
PARTITION p0 VALUES LESS THAN (
6
),
PARTITION p1 VALUES LESS THAN (
11
),
PARTITION p2 VALUES LESS THAN (
16
),
PARTITION p3 VALUES LESS THAN MAXVALUE
);
|
MAXVALUE 表示最大的可能的整數值。現在,store_id 列值大於或等於16(定義了的最高值)的所有行都將保存在分區p3中。在將來的某個時候,當商店數已經增長到25, 30, 或更多 ,可以使用ALTER TABLE語句為商店21-25, 26-30,等等增加新的分區。
在幾乎一樣的結構中,你還可以基於雇員的工作代碼來分割表,也就是說,基於job_code 列值的連續區間。例如——假定2位數字的工作代碼用來表示普通(店內的)工人,三個數字代碼表示辦公室和支持人員,四個數字代碼表示管理層,你可以使用下面的語句創建該分區表:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(
30
),
lname VARCHAR(
30
),
hired DATE NOT NULL DEFAULT
'1970-01-01'
,
separated DATE NOT NULL DEFAULT
'9999-12-31'
,
job_code INT NOT NULL,
store_id INT NOT NULL
)
PARTITION BY RANGE (job_code) (
PARTITION p0 VALUES LESS THAN (
100
),
PARTITION p1 VALUES LESS THAN (
1000
),
PARTITION p2 VALUES LESS THAN (
10000
)
);
|
在VALUES LESS THAN 子句中使用一個表達式也是可能的。這里最值得注意的限制是MySQL 必須能夠計算表達式的返回值作為LESS THAN (<)比較的一部分;因此,表達式的值不能為NULL 。由於這個原因,雇員表的hired, separated, job_code,和store_id列已經被定義為非空(NOT NULL)。
除了可以根據商店編號分割表數據外,你還可以使用一個基於兩個DATE (日期)中的一個的表達式來分割表數據。例如,假定你想基於每個雇員離開公司的年份來分割表,也就是說,YEAR(separated)的值。實現這種分區模式的CREATE TABLE 語句的一個例子如下所示:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(
30
),
lname VARCHAR(
30
),
hired DATE NOT NULL DEFAULT
'1970-01-01'
,
separated DATE NOT NULL DEFAULT
'9999-12-31'
,
job_code INT,
store_id INT
)
PARTITION BY RANGE (YEAR(separated)) (
PARTITION p0 VALUES LESS THAN (
1991
),
PARTITION p1 VALUES LESS THAN (
1996
),
PARTITION p2 VALUES LESS THAN (
2001
),
PARTITION p3 VALUES LESS THAN MAXVALUE
);
|
1)、 當需要刪除一個分區上的“舊的”數據時,只刪除分區即可。如果你使用上面最近的那個例子給出的分區方案,你只需簡單地使用 “ALTER TABLE employees DROP PARTITION p0;”來刪除所有在1991年前就已經停止工作的雇員相對應的所有行。對於有大量行的表,這比運行一個如“DELETE FROM employees WHERE YEAR (separated) <= 1990;”這樣的一個DELETE查詢要有效得多。
3)、經常運行直接依賴於用於分割表的列的查詢。例如,當執行一個如“SELECT COUNT(*) FROM employees WHERE YEAR(separated) = 2000 GROUP BY store_id;”這樣的查詢時,MySQL可以很迅速地確定只有分區p2需要掃描,這是因為余下的分區不可能包含有符合該WHERE子句的任何記錄。
2.LIST分區
LIST分區通過使用“PARTITION BY LIST(expr)”來實現,其中“expr” 是某列值或一個基於某個列值、並返回一個整數值的表達式,然后通過“VALUES IN (value_list)”的方式來定義每個分區,其中“value_list”是一個通過逗號分隔的整數列表。
注釋:在MySQL 5.1中,當使用LIST分區時,有可能只能匹配整數列表。
|
1
2
3
4
5
6
7
8
9
|
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(
30
),
lname VARCHAR(
30
),
hired DATE NOT NULL DEFAULT
'1970-01-01'
,
separated DATE NOT NULL DEFAULT
'9999-12-31'
,
job_code INT,
store_id INT
);
|
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(
30
),
lname VARCHAR(
30
),
hired DATE NOT NULL DEFAULT
'1970-01-01'
,
separated DATE NOT NULL DEFAULT
'9999-12-31'
,
job_code INT,
store_id INT
)
PARTITION BY LIST(store_id)
PARTITION pNorth VALUES IN (
3
,
5
,
6
,
9
,
17
),
PARTITION pEast VALUES IN (
1
,
2
,
10
,
11
,
19
,
20
),
PARTITION pWest VALUES IN (
4
,
12
,
13
,
14
,
18
),
PARTITION pCentral VALUES IN (
7
,
8
,
15
,
16
)
);
|
|
1
|
INSERT INTO employees VALUES(
224
,
'Linus'
,
'Torvalds'
,
'2002-05-01'
,
'2004-10-12'
,
42
,
21
);
|
LIST分區除了能和RANGE分區結合起來生成一個復合的子分區,與HASH和KEY分區結合起來生成復合的子分區也是可能的。
3.HASH分區
要使用HASH分區來分割一個表,要在CREATE TABLE 語句上添加一個“PARTITION BY HASH (expr)”子句,其中“expr”是一個返回一個整數的表達式。它可以僅僅是字段類型為MySQL 整型的一列的名字。此外,你很可能需要在后面再添加一個“PARTITIONS num”子句,其中num 是一個非負的整數,它表示表將要被分割成分區的數量。
|
1
2
3
4
5
6
7
8
9
10
11
|
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(
30
),
lname VARCHAR(
30
),
hired DATE NOT NULL DEFAULT
'1970-01-01'
,
separated DATE NOT NULL DEFAULT
'9999-12-31'
,
job_code INT,
store_id INT
)
PARTITION BY HASH(store_id)
PARTITIONS
4
;
|
|
1
2
3
4
5
6
7
8
9
10
11
|
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(
30
),
lname VARCHAR(
30
),
hired DATE NOT NULL DEFAULT
'1970-01-01'
,
separated DATE NOT NULL DEFAULT
'9999-12-31'
,
job_code INT,
store_id INT
)
PARTITION BY LINEAR HASH(YEAR(hired))
PARTITIONS
4
;
|
|
1
2
3
4
|
V = POWER(
2
, CEILING(LOG(
2
,
7
))) =
8
N = YEAR(
'2003-04-14'
) & (
8
-
1
)
=
2003
&
7
=
3
|
|
1
2
3
4
5
6
7
8
|
V =
8
N = YEAR(
'1998-10-19'
) & (
8
-
1
)
=
1998
&
7
=
6
(
6
>=
4
為真(TRUE): 還需要附加的步驟)
N =
6
& CEILING(
5
/
2
)
=
6
&
3
=
2
|
4.KSY分區
|
1
2
3
4
5
6
7
|
CREATE TABLE tk (
col1 INT NOT NULL,
col2 CHAR(
5
),
col3 DATE
)
PARTITION BY LINEAR KEY (col1)
PARTITIONS
3
;
|
========================
1、建立分區表
CREATE TABLE sale_data (
sale_date DATETIME NOT NULL,
ale_item VARCHAR(2) NOT NULL,
sale_money DECIMAL(10,2) NOT NULL
)
PARTITION BY RANGE ((year(sale_date)*100+month(sale_date))*100+day(sale_date)) (
PARTITION s20100401 VALUES LESS THAN (20100402),
PARTITION s20100402 VALUES LESS THAN (20100403),
PARTITION s20100403 VALUES LESS THAN (20100404),
PARTITION s20100404 VALUES LESS THAN (20100405),
PARTITION s20100405 VALUES LESS THAN (20100406),
PARTITION s20100406 VALUES LESS THAN (20100407),
PARTITION p1 VALUES LESS THAN (MAXVALUE)
);
2、增加分區
PARTITION p1 VALUES LESS THAN (MAXVALUE) 這句要去掉,才可以增加分區
ALTER TABLE sale_data
ADD PARTITION (PARTITION s20100402 VALUES LESS THAN (20100403));
3、刪除分區
ALTER TABLE sale_data DROP PARTITION s20100406 ;
4、正常使用
insert into sale_data values('2010-04-01','11',11.11);
insert into sale_data values('2010-04-02','22',22.22);
5、查看數據是否已經分區保存
SELECT PARTITION_NAME,TABLE_ROWS
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_NAME = 'sale_data';
+----------------+------------+
| PARTITION_NAME | TABLE_ROWS |
+----------------+------------+
| s20100401 | 1 |
| s20100402 | 1 |
+----------------+------------+
2 rows in set (0.09 sec)
