http://hi.baidu.com/jxvip/item/d6084ea5094229258919d30c mysql
http://lehsyh.iteye.com/blog/732719 mysql的表分區算法
分區的一些優勢:sql
1)與單個磁盤或文件系統分區相比,能夠存儲更多的數據。數據庫
2)對於那些已經失去保存意義的數據,一般能夠經過刪除與那些數據有關的分區,很容易地刪除那些數據。相反地,在某些狀況下,添加新數據的過程又能夠經過爲那些新數據專門增長一個新的分區來很方便地實現。服務器
3)一些查詢能夠獲得極大的優化,這主要是藉助於知足一個給定where 語句的數據能夠只保存在一個或多個分區內,這樣在查找時就不用查找其餘剩餘的分區。由於分區能夠在建立了分區表後進行修改,因此在第一次配置分區方案時還 未曾這麼作時,能夠從新組織數據,來提升那些經常使用查詢的效率。less
4)涉及到例如sum() 和 count()這樣聚合函數的查詢,能夠很容易地進行並行處理。這種查詢的一個簡單例子如 「select salesperson_id, count(orders) as order_total from sales group by salesperson_id;」。經過「並行」, 這意味着該查詢能夠在每一個分區上同時進行,最終結果只需經過總計全部分區獲得的結果。函數
5)經過跨多個磁盤來分散數據查詢,來得到更大的查詢吞吐量。優化
mysql支持的分區類型spa
range 分區:基於屬於一個給定連續區間的列值進行分配code
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
);
list 分區:相似range分區,它們的主要區別在於,list分區中每一個分區的定義和選擇是基於某列的值從屬於一個集合,而range分區是從屬於一個連續區間值的集合
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)
)
若是試圖插入列值(或分區表達式的返回值)不在分區值列表中的一行時,那麼「insert」查詢將失敗並報錯
hash分區:基於用戶定義的表達式的返回值來進行選擇的分區,該表達式使用將要插入到表中的這些行的列值進行計算。這個函數能夠包含mysql 中有效的、產生非負整數值的任何表達式。
hash分區主要用來確保數據在預先肯定數目的分區中平均分佈。在range和list分區中,必須明確指定一個給定的列值或列值集合應該保存在哪 個分區中;而在hash分區中,mysql 自動完成這些工做,你所要作的只是基於將要被哈希的列值指定一個列值或表達式,以及指定被分區的表將要被分割成的分區數量。
要使用hash分區來分割一個表,要在create table 語句上添加一個「partition by hash (expr)」子句,其中「expr」是一個返回一個整數的表達式。它能夠僅僅是字段類型爲mysql 整型的一列的名字。此外,你極可能須要在後面再添加一個「partitions num」子句,其中num 是一個非負的整數,它表示表將要被分割成分區的數量。
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(year(hired))
partitions 4;
mysql還支持線性哈希功能,它與常規哈希的區別在於,線性哈希功能使用的一個線性的2的冪(powers-of-two)運算法則,而常規 哈希使用的是求哈希函數值的模數。
線性哈希分區和常規哈希分區在語法上的惟一區別在於,在「partition by」 子句中添加「linear」關鍵字,以下面所示:
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;
按照線性哈希分區的優勢在於增長、刪除、合併和拆分分區將變得更加快捷,有利於處理含有極其大量(1000g)數據的表。它的缺點在於,與使用常規hash分區獲得的數據分佈相比,各個分區間數據的分佈不大可能均衡。
key 分區:按照key進行分區相似於按照hash分區,除了hash分區使用的用戶定義的表達式,而key分區的 哈希函數是由mysql 服務器提供。mysql 簇(cluster)使用函數md5()來實現key分區
對於使用其餘存儲引擎的表,服務器使用其本身內部的 哈希函數,這些函數是基於與password()同樣的運算法則
經過線性key分割一個表也是可能的。下面是一個簡單的例子:
create table tk (
col1 int not null,
col2 char(5),
col3 date
)
partition by linear key (col1)
partitions 3;
子分區:子分區是分區表中每一個分區的再次分割
create table ts (id int, purchased date)
partition by range(year(purchased))
subpartition by hash(to_days(purchased))
(
partition p0 values less than (1990)
(
subpartition s0,
subpartition s1
),
partition p1 values less than (2000)
(
subpartition s2,
subpartition s3
),
partition p2 values less than maxvalue
(
subpartition s4,
subpartition s5
)
);
子分區能夠用於特別大的表,在多個磁盤間分配數據和索引。假設有6個磁盤,分別爲/disk0, /disk1, /disk2等。如今考慮下面的例子:
create table ts (id int, purchased date)
partition by range(year(purchased))
subpartition by hash(to_days(purchased))
(
partition p0 values less than (1990)
(
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 (2000)
(
subpartition s0
data directory = '/disk2/data'
index directory = '/disk2/idx',
subpartition s1
data directory = '/disk3/data'
index directory = '/disk3/idx'
),
partition p2 values less than maxvalue
(
subpartition s0
data directory = '/disk4/data'
index directory = '/disk4/idx',
subpartition s1
data directory = '/disk5/data'
index directory = '/disk5/idx'
)
)
分區管理
從一個按照range或list分區的表中刪除一個分區,可使用帶一個drop partition子句的alter table命令來實現
alter table tr drop partition p2;
由「alter table … drop partition」語句引發的、從表中刪除的行數並無被服務器報告出來
若是但願改變表的分區而又不丟失數據,使用「alter table … reorganize partition」語句
一個reorganize partition語句也能夠用來合併相鄰的分區。可使用以下的語句恢復成員表到它之前的分區:
alter table members reorganize partition s0,s1 into (
partition p0 values less than (1970)
);
使用「reorganize partition」拆分或合併分區,沒有數據丟失。在執行上面的語句中,mysql 把保存在分區s0和s1中的全部數據都移到分區p0中。
「reorganize partition」的基本語法是:
alter table tbl_name reorganize partition partition_list into (partition_definitions);
不能使用與從按照range或list分區的表中刪除分區相同的方式來從hash或key分區的表中刪除分區。可是,可使用「alter table … coalesce partition」命令來合併hash或key分區。
coalesce不能用來增長分區的數量,要增長顧客表的分區數量從12到18,使用「alter table … add partition」,具體以下:
alter table clients add partition partitions 6;