1扇售、分區(qū)概念
mysql數(shù)據(jù)庫中的數(shù)據(jù)是以文件的形勢存在磁盤上的,默認(rèn)放在/mysql/data下面(可以通過my.cnf中的datadir來查看)岛宦,一張表主要對應(yīng)著三個文件(8.0對應(yīng)兩個丽焊,往期版本三個)一個是frm存放表結(jié)構(gòu)的,一個是myd存放表數(shù)據(jù)的纬朝,一個是myi存表索引的(innodb同理)。
如果一張表的數(shù)據(jù)量太大的話骄呼,那么myd,myi就會變的很大共苛,查找數(shù)據(jù)就會變的很慢,這個時候我們可以利用mysql的分區(qū)功能蜓萄,在物理上將這一張表對應(yīng)的三個文件隅茎,分割成許多個小塊,這樣呢嫉沽,我們查找一條數(shù)據(jù)時辟犀,就不用全部查找了,只要知道這條數(shù)據(jù)在哪一塊耻蛇,然后在那一塊找就行了踪蹬。如果表的數(shù)據(jù)太大胞此,可能一個磁盤放不下臣咖,這個時候,我們可以把數(shù)據(jù)分配到不同的磁盤里面去漱牵。
表分區(qū)夺蛇,是指根據(jù)一定規(guī)則,將數(shù)據(jù)庫中的一張表分解成多個更小的酣胀,容易管理的部分刁赦。從邏輯上看隔节,只有一張表衔统,但是底層卻是由多個物理分區(qū)組成盹憎。
2仍律、分區(qū)優(yōu)點
- 與單個磁盤或文件系統(tǒng)分區(qū)相比强胰,可以存儲更多的數(shù)據(jù)嫁怀。
- 對于那些已經(jīng)失去保存意義的數(shù)據(jù)牵触,通巢菽龋可以通過刪除與那些數(shù)據(jù)有關(guān)的分區(qū)墩剖,很容易地刪除那些數(shù)據(jù)猴凹。相反地,在某些情況下岭皂,添加新數(shù)據(jù)的過程又可以通過為那些新數(shù)據(jù)專門增加一個新的分區(qū)郊霎,來很方便地實現(xiàn)。
- 一些查詢可以得到極大的優(yōu)化爷绘,這主要是借助于滿足一個給定WHERE語句的數(shù)據(jù)可以只保存在一個或多個分區(qū)內(nèi)书劝,這樣在查找時就不用查找其他剩余的分區(qū)进倍。因為分區(qū)可以在創(chuàng)建了分區(qū)表后進(jìn)行修改,所以在第一次配置分區(qū)方案時還不曾這么做時购对,可以重新組織數(shù)據(jù)背捌,來提高那些常用查詢的效率。
- 涉及到例如SUM()和COUNT()這樣聚合函數(shù)的查詢洞斯,可以很容易地進(jìn)行并行處理毡庆。這種查詢的一個簡單例子如 “SELECT salesperson_id, COUNT (orders) as order_total FROM sales GROUP BY salesperson_id;”烙如。通過“并行”么抗,這意味著該查詢可以在每個分區(qū)上同時進(jìn)行,最終結(jié)果只需通過總計所有分區(qū)得到的結(jié)果亚铁。
- 通過跨多個磁盤來分散數(shù)據(jù)查詢蝇刀,來獲得更大的查詢吞吐量。
3徘溢、分區(qū)限制
- 一個表最多只能有1024個分區(qū)吞琐。
- MySQL5.1中,分區(qū)表達(dá)式必須是整數(shù)然爆,或者返回整數(shù)的表達(dá)式站粟。在MySQL5.5中提供了非整數(shù)表達(dá)式分區(qū)的支持。
- 如果分區(qū)字段中有主鍵或者唯一索引的列曾雕,那么所有主鍵列和唯一索引列都必須包含進(jìn)來奴烙。即:分區(qū)字段要么不包含主鍵或者索引列,要么包含全部主鍵和索引列剖张。
- 分區(qū)表中無法使用外鍵約束切诀。
- MySQL的分區(qū)適用于一個表的所有數(shù)據(jù)和索引,不能只對表數(shù)據(jù)分區(qū)而不對索引分區(qū)搔弄,也不能只對索引分區(qū)而不對表分區(qū)幅虑,也不能只對表的一部分?jǐn)?shù)據(jù)分區(qū)。
4顾犹、分區(qū)類型
- RANGE分區(qū):基于屬于一個給定連續(xù)區(qū)間的列值倒庵,把多行分配給分區(qū)。
range分區(qū)使用values less than 操作符來進(jìn)行定義蹦渣, 把連續(xù)且不相互重疊的字段分配給分區(qū)哄芜,命令如下。
create table emp(
`no` varchar(20) not null,
`name` varchar(20),
deptno int,
birthdate date,
salary int
)
partition by range(salary) (
partition p1 values less than(1000),
partition p2 values less than(5000),
partition p3 values less than(10000)
);
insert into emp values('001', 'shineyork', 10, '2019-10-10', 5000);
insert into emp values('002', 'keke', 20, '2019-10-10', 1500);
insert into emp values('004', 'n', 20, '2019-10-10', 1000);
insert into emp values('004', 'c', 20, '2019-10-10', 6000);
如上的方式就是把數(shù)據(jù)根據(jù)salary的value進(jìn)行劃分柬唯,區(qū)分到不同的表分區(qū)中认臊;而這其中partition by range的語法類似于“switch..case”的語法,如果salary小余5000就會在p1中...當(dāng)salary大于10000會報錯
mysql> insert into emp values('003', 'a', 10, '2019-10-10', 10500);
ERROR 1526 (HY000): Table has no partition for value 10500
這是因為10000不在分區(qū)范圍內(nèi)锄奢,解決這個問題的辦法就是在其后加入“partition p4 values less than maxvalue” 語法失晴,這樣所有大于10000的數(shù)據(jù)都會存在p4分區(qū)中
partition by range(salary) (
partition p1 values less than(1000),
partition p2 values less than(5000),
partition p3 values less than(10000),
partition p4 values less than maxvalue
)
查詢分區(qū)之后某一個區(qū)中的數(shù)據(jù)
select * from emp partition (p3);
在range中也可以使用MySQL的系統(tǒng)函數(shù)剧腻,比如根據(jù)年齡進(jìn)行區(qū)分
create table emp(
`no` varchar(20) not null,
`name` varchar(20),
deptno int,
birthdate date,
salary int
)
partition by range(year(birthdate)) (
partition p1 values less than(1990),
partition p2 values less than(2000),
partition p3 values less than(2010),
partition p4 values less than maxvalue
)
- LIST分區(qū):類似于range分區(qū),區(qū)別在于list中的每個分區(qū)的定義和選擇基于某列的值從屬于一個集合涂屁,而range分區(qū)是屬于一個連續(xù)區(qū)間值得集合书在。
create table emp(
`no` varchar(20) not null,
`name` varchar(20),
deptno int,
birthdate date,
salary int
)
partition by list(deptno) (
partition p1 values in (10,20,30),
partition p2 values in (1,2,3),
partition p4 values in (4,40)
);
insert into emp values('001', 'shineyork', 1, '2019-10-10', 5000);
insert into emp values('002', 'keke', 20, '2019-10-10', 1500);
insert into emp values('003', 'a', 10, '2019-10-10', 10500);
insert into emp values('004', 'n', 40, '2019-10-10', 1000);
insert into emp values('005', 'c', 6, '2019-10-10', 6000);
mysql> insert into emp values('005', 'c', 6, '2019-10-10', 6000);
ERROR 1526 (HY000): Table has no partition for value 6
- HASH分區(qū):HASH分區(qū)是基于用戶定義的表達(dá)式的返回值來進(jìn)行選擇的分區(qū),該表達(dá)式使用將要插入到表中的這些行的列值進(jìn)行計算拆又。這個函數(shù)可以包含MySQL中有效的儒旬、產(chǎn)生非負(fù)整數(shù)值的任何表達(dá)式。
HASH分區(qū)主要用來確保數(shù)據(jù)在預(yù)先確定數(shù)目的分區(qū)中平均分布帖族。 在RANGE和LIST分區(qū)中栈源,必須明確指定一個給定的列值或列值集合應(yīng)該保存在哪個分區(qū)中;而在HASH分區(qū)中竖般,MySOL自動完成這些工作甚垦,用戶所要做的只是基于將要被哈希的列值指定一個列值或表達(dá)式,以及指定被分區(qū)的表將要被分割成的分區(qū)數(shù)量涣雕。
create table emp(
`no` varchar(20) not null,
`name` varchar(20),
deptno int,
birthdate date,
salary int
)
partition by hash(year(birthdate)) partitions 4;
- KEY分區(qū):類似于hash分區(qū)艰亮,區(qū)別在于key分區(qū)只支持計算一列或多列,且MySQL服務(wù)器其自身的哈希函數(shù)挣郭,必須有一列或多列包含整數(shù)值迄埃。這些函數(shù)是基于password()一樣的運算規(guī)則
create table emp(
`no` varchar(20) not null,
`name` varchar(20),
deptno int,
birthdate date,
salary int
)
partition by key(year(birthdate)) partitions 4;
*說明:在MySQL5.1版本中,RANGE,LIST,HASH分區(qū)要求分區(qū)鍵必須是INT類型丈屹,或者通過表達(dá)式返回INT類型调俘。但KEY分區(qū)的時候伶棒,可以使用其他類型的列(BLOB旺垒,TEXT類型除外)作為分區(qū)鍵。