如下四種數據庫的分區我只實現了下RANGE(範圍)分區 還有三種以後都會嘗試去實現 有實現的朋友能夠分享下本身以爲寫的不錯的相關文章html
1、什麼是表分區
通俗地講表分區是將一大表,根據條件分割成若干個小表。mysql5.1開始支持數據表分區了。 如:某用戶表的記錄超過了600萬條,那麼就能夠根據入庫日期將表分區,也能夠根據所在地將表分區。固然也可根據其餘的條件分區。mysql
2、爲何要對錶進行分區
爲了改善大型表以及具備各類訪問模式的表的可伸縮性,可管理性和提升數據庫效率。算法
分區的一些優勢包括:sql
與單個磁盤或文件系統分區相比,能夠存儲更多的數據。
對於那些已經失去保存意義的數據,一般能夠經過刪除與那些數據有關的分區,很容易地刪除那些數據。相反地,在某些狀況下,添加新數據的過程又能夠經過爲那些新數據專門增長一個新的分區,來很方便地實現。一般和分區有關的其餘優勢包括下面列出的這些。MySQL分區中的這些功能目前尚未實現,可是在咱們的優先級列表中,具備高的優先級;咱們但願在5.1的生產版本中,能包括這些功能。
一些查詢能夠獲得極大的優化,這主要是藉助於知足一個給定WHERE語句的數據能夠只保存在一個或多個分區內,這樣在查找時就不用查找其餘剩餘的分區。由於分區能夠在建立了分區表後進行修改,因此在第一次配置分區方案時還未曾這麼作時,能夠從新組織數據,來提升那些經常使用查詢的效率。
涉及到例如SUM()和COUNT()這樣聚合函數的查詢,能夠很容易地進行並行處理。這種查詢的一個簡單例子如 「SELECT salesperson_id, COUNT (orders) as order_total FROM sales GROUP BY salesperson_id;」。經過「並行」,這意味着該查詢能夠在每一個分區上同時進行,最終結果只需經過總計全部分區獲得的結果。
經過跨多個磁盤來分散數據查詢,來得到更大的查詢吞吐量。
3、分區類型
RANGE分區:基於屬於一個給定連續區間的列值,把多行分配給分區。數據庫
LIST分區:相似於按RANGE分區,區別在於LIST分區是基於列值匹配一個離散值集合中的某個值來進行選擇。服務器
HASH分區:基於用戶定義的表達式的返回值來進行選擇的分區,該表達式使用將要插入到表中的這些行的列值進行計算。這個函數能夠包含MySQL 中有效的、產生非負整數值的任何表達式。ide
KEY分區:相似於按HASH分區,區別在於KEY分區只支持計算一列或多列,且MySQL服務器提供其自身的哈希函數。必須有一列或多列包含整數值。函數
基於屬於一個給定連續區間的列值,把多行分配給分區。優化
這些區間要連續且不能相互重疊,使用VALUES LESS THAN操做符來進行定義。如下是實例。code
Sql代碼:
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)
);
按照這種分區方案,在商店1到5工做的僱員相對應的全部行被保存在分區P0中,商店6到10的僱員保存在P1中,依次類推。注意,每一個分區都是按順序進行定義,從最低到最高。這是PARTITION BY RANGE 語法的要求;在這點上,它相似於C或Java中的「switch … case」語句。對於包含數據(72, ‘Michael’, ‘Widenius’, ’1998-06-25′, NULL, 13)的一個新行,能夠很容易地肯定它將插入到p2分區中,可是若是增長了一個編號爲第21的商店,將會發生什麼呢?在這種方案下,因爲沒有規則把store_id大於20的商店包含在內,服務器將不知道把該行保存在何處,將會致使錯誤。 要避免這種錯誤,能夠經過在CREATE TABLE語句中使用一個「catchall」 VALUES LESS THAN子句,該子句提供給全部大於明確指定的最高值的值:
Sql代碼:
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位數字的工做代碼用來表示普通(店內的)工人,三個數字代碼表示辦公室和支持人員,四個數字代碼表示管理層,你可使用下面的語句建立該分區表:
Sql代碼:
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)
);
在這個例子中, 店內工人相關的全部行將保存在分區p0中,辦公室和支持人員相關的全部行保存在分區p1中,管理層相關的全部行保存在分區p2中。在VALUES LESS THAN 子句中使用一個表達式也是可能的。這裏最值得注意的限制是MySQL 必須可以計算表達式的返回值做爲LESS THAN (<)比較的一部分;所以,表達式的值不能爲NULL 。因爲這個緣由,僱員表的hired, separated, job_code,和store_id列已經被定義爲非空(NOT NULL)。除了能夠根據商店編號分割表數據外,你還可使用一個基於兩個DATE (日期)中的一個的表達式來分割表數據。例如,假定你想基於每一個僱員離開公司的年份來分割表,也就是說,YEAR(separated)的值。實現這種分區模式的CREATE TABLE 語句的一個例子以下所示:
Sql代碼:
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
);
在這個方案中,在1991年前僱傭的全部僱員的記錄保存在分區p0中,1991年到1995年期間僱傭的全部僱員的記錄保存在分區p1中, 1996年到2000年期間僱傭的全部僱員的記錄保存在分區p2中,2000年後僱傭的全部工人的信息保存在p3中。
RANGE分區在以下場合特別有用:1)、當須要刪除一個分區上的「舊的」數據時,只刪除分區便可。若是你使用上面最近的那個例子給出的分區方案,你只需簡單地使用」ALTER TABLE employees DROP PARTITION p0;」來刪除全部在1991年前就已經中止工做的僱員相對應的全部行。對於有大量行的表,這比運行一個如」DELETE FROM employees WHERE YEAR (separated) <= 1990;」這樣的一個DELETE查詢要有效得多。 2)、想要使用一個包含有日期或時間值,或包含有從一些其餘級數開始增加的值的列。3)、常常運行直接依賴於用於分割表的列的查詢。例如,當執行一個如」SELECT COUNT(*) FROM employees WHERE YEAR(separated) = 2000 GROUP BY store_id;」這樣的查詢時,MySQL能夠很迅速地肯定只有分區p2須要掃描,這是由於餘下的分區不可能包含有符合該WHERE子句的任何記錄。
註釋:這種優化尚未在MySQL 5.1源程序中啓用,可是,有關工做正在進行中。
相似於按RANGE分區,區別在於LIST分區是基於列值匹配一個離散值集合中的某個值來進行選擇。
LIST分區經過使用「PARTITION BY LIST(expr)」來實現,其中「expr」是某列值或一個基於某個列值、並返回一個整數值的表達式,而後經過「VALUES IN (value_list)」的方式來定義每一個分區,其中「value_list」是一個經過逗號分隔的整數列表。 註釋:在MySQL 5.1中,當使用LIST分區時,有可能只能匹配整數列表。
Sql代碼:
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
);
假定有20個音像店,分佈在4個有經銷權的地區,以下表所示:
====================
地區 商店ID 號
北區 3, 5, 6, 9, 17
東區 1, 2, 10, 11, 19, 20
西區 4, 12, 13, 14, 18
中心區 7, 8, 15, 16
====================
要按照屬於同一個地區商店的行保存在同一個分區中的方式來分割表,可使用下面的「CREATE TABLE」語句:
Sql代碼:
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)
);
這使得在表中增長或刪除指定地區的僱員記錄變得容易起來。例如,假定西區的全部音像店都賣給了其餘公司。那麼與在西區音像店工做僱員相關的全部記錄(行)可使用查詢「ALTER TABLE employees DROP PARTITION pWest;」來進行刪除,它與具備一樣做用的DELETE(刪除)查詢「DELETE query DELETE FROM employees WHERE store_id IN (4,12,13,14,18);」比起來,要有效得多。【要點】:若是試圖插入列值(或分區表達式的返回值)不在分區值列表中的一行時,那麼「INSERT」查詢將失敗並報錯。例如,假定LIST分區的採用上面的方案,下面的查詢將失敗:
Sql代碼:
INSERT INTO employees VALUES(224, 'Linus', 'Torvalds', '2002-05-01', '2004-10-12', 42, 21);
這是由於「store_id」列值21不能在用於定義分區pNorth, pEast, pWest,或pCentral的值列表中找到。要重點注意的是,LIST分區沒有相似如「VALUES LESS THAN MAXVALUE」這樣的包含其餘值在內的定義。將要匹配的任何值都必須在值列表中找到。
LIST分區除了能和RANGE分區結合起來生成一個複合的子分區,與HASH和KEY分區結合起來生成複合的子分區也是可能的。
基於用戶定義的表達式的返回值來進行選擇的分區,該表達式使用將要插入到表中的這些行的列值進行計算。這個函數能夠包含MySQL 中有效的、產生非負整數值的任何表達式。
要使用HASH分區來分割一個表,要在CREATE TABLE 語句上添加一個「PARTITION BY HASH (expr)」子句,其中「expr」是一個返回一個整數的表達式。它能夠僅僅是字段類型爲MySQL整型的一列的名字。此外,你極可能須要在後面再添加一個「PARTITIONS num」子句,其中num是一個非負的整數,它表示表將要被分割成分區的數量。
Sql代碼:
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;
若是沒有包括一個PARTITIONS子句,那麼分區的數量將默認爲1。例外:對於NDB Cluster(簇)表,默認的分區數量將與簇數據節點的數量相同,這種修正多是考慮任何MAX_ROWS設置,以便確保全部的行都能合適地插入到分區中。
LINER HASH
MySQL還支持線性哈希功能,它與常規哈希的區別在於,線性哈希功能使用的一個線性的2的冪(powers-of-two)運算法則,而常規哈希使用的是求哈希函數值的模數。線性哈希分區和常規哈希分區在語法上的惟一區別在於,在「PARTITION BY」子句中添加「LINEAR」關鍵字。
Sql代碼:
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;
假設一個表達式expr,當使用線性哈希功能時,記錄將要保存到的分區是num 個分區中的分區N,其中N是根據下面的算法獲得: 1. 找到下一個大於num.的、2的冪,咱們把這個值稱爲V ,它能夠經過下面的公式獲得: 2. V = POWER(2, CEILING(LOG(2, num))) (例如,假定num是13。那麼LOG(2,13)就是3.7004397181411。 CEILING(3.7004397181411)就是4,則V = POWER(2,4), 即等於16)。 3. 設置 N = F(column_list) & (V – 1). 4. 當 N >= num: · 設置 V = CEIL(V / 2) · 設置 N = N & (V – 1) 例如,假設表t1,使用線性哈希分區且有4個分區,是經過下面的語句建立的: CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATE) PARTITION BY LINEAR HASH( YEAR(col3) ) PARTITIONS 6; 如今假設要插入兩行記錄到表t1中,其中一條記錄col3列值爲’2003-04-14′,另外一條記錄col3列值爲’1998-10-19′。第一條記錄將要保存到的分區肯定以下: V = POWER(2, CEILING(LOG(2,7))) = 8 N = YEAR(’2003-04-14′) & (8 – 1) = 2003 & 7 = 3 (3 >= 6 爲假(FALSE): 記錄將被保存到#3號分區中) 第二條記錄將要保存到的分區序號計算以下: V = 8 N = YEAR(’1998-10-19′) & (8-1) = 1998 & 7 = 6 (6 >= 4 爲真(TRUE): 還須要附加的步驟) N = 6 & CEILING(5 / 2) = 6 & 3 = 2 (2 >= 4 爲假(FALSE): 記錄將被保存到#2分區中) 按照線性哈希分區的優勢在於增長、刪除、合併和拆分分區將變得更加快捷,有利於處理含有極其大量(1000吉)數據的表。它的缺點在於,與使用常規HASH分區獲得的數據分佈相比,各個分區間數據的分佈不大可能均衡。
相似於按HASH分區,區別在於KEY分區只支持計算一列或多列,且MySQL服務器提供其自身的哈希函數。必須有一列或多列包含整數值。
Sql代碼:
CREATE TABLE tk (
col1 INT NOT NULL, col2 CHAR(5), col3 DATE
)
PARTITION BY LINEAR KEY (col1)
PARTITIONS 3;
在KEY分區中使用關鍵字LINEAR和在HASH分區中使用具備一樣的做用,分區的編號是經過2的冪(powers-of-two)算法獲得,而不是經過模數算法。