MYSQL性能優(yōu)化之分區(qū)表(未完待續(xù))

前言

了解分區(qū)表之前需要知道渔彰,我們先來(lái)看一看Mysql對(duì)分區(qū)的解釋?zhuān)旅嬉欢卧?huà)摘自官網(wǎng)嵌屎。

SQL標(biāo)準(zhǔn)不會(huì)特別關(guān)注數(shù)據(jù)的物理存儲(chǔ),SQL語(yǔ)言本身則傾向獨(dú)立于它所使用的模式恍涂、表宝惰、行或列底層的
任何數(shù)據(jù)結(jié)構(gòu)或存儲(chǔ)媒介。盡管如此再沧,大多數(shù)高級(jí)數(shù)據(jù)庫(kù)管理系統(tǒng)已經(jīng)可以根據(jù)文件系統(tǒng)尼夺、硬件或者同時(shí)
根據(jù)文件系統(tǒng)和硬件來(lái)確定特定數(shù)據(jù)塊的物理位置。MySQL中,InnoDB存儲(chǔ)引擎一直支持表空間(table
space)的概念,甚至引入分區(qū)前MySQL服務(wù)器就支持配置不同的物理目錄用于存儲(chǔ)不同的數(shù)據(jù)庫(kù).
分區(qū)(Partitioning)使這個(gè)概念更進(jìn)了一步炒瘸,它允許根據(jù)實(shí)際需求設(shè)置的規(guī)則將表的各個(gè)部分跨文件
系統(tǒng)打散(實(shí)際上指的是表的水平拆分)淤堵。實(shí)際上,表的不同部分作為單獨(dú)的分區(qū)表存儲(chǔ)在不同的位置顷扩。
用戶(hù)選擇的數(shù)據(jù)劃分規(guī)則被稱(chēng)為分區(qū)函數(shù)拐邪,在MySQL中,它可以是模數(shù)隘截、對(duì)一組范圍或值列表的簡(jiǎn)單匹
配扎阶、內(nèi)部哈希函數(shù)或線(xiàn)性哈希函數(shù)。根據(jù)用戶(hù)指定的分區(qū)類(lèi)型選擇函數(shù)婶芭,并將用戶(hù)提供的表達(dá)式的值作為
其參數(shù)乘陪。這個(gè)表達(dá)式可以是一個(gè)列值、一個(gè)作用于一個(gè)或多個(gè)列值的函數(shù)雕擂,或者一個(gè)或多個(gè)列值的集合啡邑,
這取決于所使用的分區(qū)類(lèi)型。
這里的分區(qū)被稱(chēng)為水平分區(qū)——也就是說(shuō)井赌,一個(gè)表的不同行可能被分配到不同的物理分區(qū)谤逼。MySQL 5.7不
支持垂直分區(qū)(表的不同列被分配到不同的物理分區(qū))。

重要:分區(qū)適用于表的所有數(shù)據(jù)和索引;不能只分區(qū)數(shù)據(jù)而不分區(qū)索引仇穗,反之亦然流部,也不能僅對(duì)表的一部分
進(jìn)行分區(qū).

官網(wǎng)的解釋可以看出,Mysql的分區(qū)是在mysql表空間概念基礎(chǔ)上的升級(jí)纹坐,支持用戶(hù)自定義規(guī)則對(duì)單表進(jìn)行分區(qū)枝冀,分散存儲(chǔ)各分區(qū)表;除此之外耘子,需要注意果漾,Mysql分區(qū)要求同一張表的所有分區(qū)必須采用相同的存儲(chǔ)引擎,這一點(diǎn)上來(lái)看谷誓,分區(qū)表與普通表對(duì)存儲(chǔ)引擎來(lái)說(shuō)沒(méi)有區(qū)別绒障;比如說(shuō)對(duì)表test來(lái)說(shuō),它的所有分區(qū)表只能采用InnoDB或者M(jìn)yISAM捍歪,不能test分區(qū)表1采用InnoDB户辱,test分區(qū)表2采用MyISAM鸵钝。但是,不同Server或者DB中的不同表的分區(qū)表可以采用不同的存儲(chǔ)引擎庐镐。Mysql僅支持水平分區(qū)(5.7版本)恩商,這是另一個(gè)需要注意的點(diǎn)。圖示如下:

mysql-分區(qū)表.jpg

一必逆、分區(qū)優(yōu)點(diǎn)及使用場(chǎng)景

通常情況下痕届,對(duì)于非常大的表,無(wú)法全部放在內(nèi)存中末患,或者只在表的最后部分有熱點(diǎn)數(shù)據(jù)研叫,適合進(jìn)行分區(qū)。分區(qū)表有以下幾個(gè)優(yōu)點(diǎn):

1璧针、數(shù)據(jù)更容易維護(hù)

便于批量處理符合條件的單個(gè)分區(qū)數(shù)據(jù)嚷炉,比如批量刪除、備份探橱、恢復(fù)等申屹;便于對(duì)獨(dú)立單個(gè)分區(qū)進(jìn)行優(yōu)化、檢查隧膏、哗讥、修復(fù)等操作。

2胞枕、數(shù)據(jù)物理隔離杆煞,高效利用物理設(shè)備

分區(qū)表數(shù)據(jù)可以分布在不同的物理設(shè)備上,從而高效利用多個(gè)物理設(shè)備腐泻。

3决乎、有效避免性能瓶頸

可以有效避免性能瓶頸,比如innodb單個(gè)索引的互斥訪(fǎng)問(wèn)派桩、ext3文件系統(tǒng)的inode(linux可以通過(guò)ls -li查看文件的inodeid)鎖競(jìng)爭(zhēng)等构诚。

二、分區(qū)表類(lèi)型

mysql 支持的分區(qū)表類(lèi)型包括:Range Partitioning(范圍分區(qū))铆惑、List Partitioning(列表分區(qū))范嘱、Column Partitioning(列分區(qū)、Hash Partitioning(hash分區(qū))员魏、KEY Partitioning(鍵值分區(qū))丑蛤、subPartitioning(子分區(qū)),幾種逆趋,下面我們按照這個(gè)順序盏阶,根據(jù)官網(wǎng)的介紹一一進(jìn)行介紹

2.1 Range Partitioning(范圍分區(qū))

范圍分區(qū)根據(jù)用戶(hù)定義的范圍規(guī)則,將指定列值在范圍內(nèi)的行記錄存儲(chǔ)至同一張分區(qū)表闻书。

例如名斟,原始單表建表語(yǔ)句:

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
);

假設(shè)這里按照列store_id進(jìn)行范圍分區(qū),sql語(yǔ)句如下:

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)
);

建表完成之后魄眉,查看表:

+----------------+
| Tables_in_test |
+----------------+
| employees      |
+----------------+
1 row in set (0.00 sec)

再來(lái)看mysql的數(shù)據(jù)文件變化砰盐,可以在mysql中執(zhí)行下列語(yǔ)句,查看當(dāng)前mysql的數(shù)據(jù)文件存儲(chǔ)位置:

SHOW VARIABLES LIKE 'datadir';
-- mac下Mysql數(shù)據(jù)的默認(rèn)存儲(chǔ)路徑是/usr/local/mysql/data/ 
-- 查看路徑下數(shù)據(jù)文件坑律,其中test是DB名稱(chēng)  sudo ls /usr/local/mysql/data/test

進(jìn)入該目錄岩梳,查看數(shù)據(jù)文件,其中,.ibd文件存儲(chǔ)的是索引與數(shù)據(jù)晃择,.frm文件則存儲(chǔ)表結(jié)構(gòu)及元數(shù)據(jù)冀值。可以看到宫屠,分區(qū)后的employees數(shù)據(jù)文件被一分為四列疗,拆分為4個(gè)ibd文件


20210902232544.jpg

回國(guó)過(guò)頭我們?cè)賮?lái)看,如果此時(shí)執(zhí)行insert語(yǔ)句浪蹂,插入一條store_id = 14的數(shù)據(jù)抵栈,那么會(huì)落在p2分區(qū);那么坤次,如果插入一條sotre_id = 30的數(shù)據(jù)古劲,此時(shí)Mysql會(huì)直接報(bào)錯(cuò),因?yàn)樵摋l數(shù)據(jù)不滿(mǎn)足當(dāng)前的分區(qū)規(guī)則缰猴,Mysql也不知道這條記錄應(yīng)該放在哪個(gè)分區(qū)产艾。當(dāng)然,Mysql也提供了解決方案滑绒,比如可以新增一個(gè)分區(qū)胰舆,用于存放分區(qū)值小于Integer.MaxValue的store_id對(duì)應(yīng)的記錄

PARTITION p4 VALUES LESS THAN MAXVALUE*

分區(qū)列除了支持int類(lèi)型外,還支持date蹬挤、timestamp

-- 按照int類(lèi)型列分區(qū)
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
);
-- 按照date分區(qū)
CREATE TABLE members (
    firstname VARCHAR(25) NOT NULL,
    lastname VARCHAR(25) NOT NULL,
    username VARCHAR(16) NOT NULL,
    email VARCHAR(35),
    joined DATE NOT NULL
)
PARTITION BY RANGE COLUMNS(joined) (
    PARTITION p0 VALUES LESS THAN ('1960-01-01'),
    PARTITION p1 VALUES LESS THAN ('1970-01-01'),
    PARTITION p2 VALUES LESS THAN ('1980-01-01'),
    PARTITION p3 VALUES LESS THAN ('1990-01-01'),
    PARTITION p4 VALUES LESS THAN MAXVALUE
);
-- 按照timestamp分區(qū)
CREATE TABLE quarterly_report_status (
    report_id INT NOT NULL,
    report_status VARCHAR(20) NOT NULL,
    report_updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)
PARTITION BY RANGE ( UNIX_TIMESTAMP(report_updated) ) (
    PARTITION p0 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-01-01 00:00:00') ),
    PARTITION p1 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-04-01 00:00:00') ),
    PARTITION p2 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-07-01 00:00:00') ),
    PARTITION p3 VALUES LESS THAN ( UNIX_TIMESTAMP('2008-10-01 00:00:00') ),
    PARTITION p4 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-01-01 00:00:00') ),
    PARTITION p5 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-04-01 00:00:00') ),
    PARTITION p6 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-07-01 00:00:00') ),
    PARTITION p7 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-10-01 00:00:00') ),
    PARTITION p8 VALUES LESS THAN ( UNIX_TIMESTAMP('2010-01-01 00:00:00') ),
    PARTITION p9 VALUES LESS THAN (MAXVALUE)
);

2.3 List Partitioning(列表分區(qū))

列表分區(qū)與范圍分區(qū)非常相似缚窿,不同之處在于,列表分區(qū)是根據(jù)分區(qū)字段值所在的散列值作為分區(qū)的規(guī)則條件焰扳。我們?nèi)砸?.2中的employees表為例:

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
);

假設(shè)現(xiàn)在有20家音像店倦零,分部在東西南北,4個(gè)區(qū)域:

RegionStore ID Numbers:
North3, 5, 6, 9, 17
East1, 2, 10, 11, 19, 20
West4, 12, 13, 14, 18
Central7, 8, 15, 16

對(duì)應(yīng)的分區(qū)建表語(yǔ)句如下:

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)
);

此次吨悍,如果老板要賣(mài)掉東部地區(qū)的音像店扫茅,那么此時(shí)可以直接刪除DB中東部的分區(qū):

-- 這要比從 DELETE FROM employees WHERE store_id IN (4,12,13,14,18)高效的多
ALTER TABLE employees TRUNCATE PARTITION pWest;

另外,與范圍分區(qū)不同之處在于育瓜,列表分區(qū)沒(méi)有兜底的方案葫隙,若當(dāng)前分區(qū)字段值不在任一個(gè)分區(qū)表達(dá)式中,那么Mysql會(huì)直接報(bào)錯(cuò):

ERROR 1525 (HY000): Table has no partition for value 3

還有一種情況需要注意躏仇,單條insert語(yǔ)句插入多條記錄時(shí)恋脚,若其中有若干條記錄的分區(qū)字段值與分區(qū)表達(dá)式不匹配腺办,那么此時(shí)Mysql是否會(huì)報(bào)錯(cuò)取決于當(dāng)前的存儲(chǔ)引擎是否支持事務(wù)。若使用Innodb糟描,那么insert會(huì)被當(dāng)做一個(gè)事務(wù)怀喉,此時(shí)失敗事務(wù)回滾,所有記錄都不會(huì)插入成功船响;若使用的是MyISAM躬拢,那么在失敗的記錄之前的記錄可以插入成功,之后的記錄不會(huì)成功见间。當(dāng)然聊闯,Mysql提供了這種問(wèn)題的規(guī)避機(jī)制,即IGNORE關(guān)鍵字米诉,此時(shí)與分區(qū)表達(dá)式不匹配的記錄不會(huì)插入菱蔬,而其他記錄會(huì)成功插入,且不會(huì)報(bào)錯(cuò)荒辕。

 INSERT IGNORE INTO employees VALUES (2,'1970-01-01','1970-01-01',1, 35), (2,'1970-01-01','1970-01-01',1, 15);

2.3 Column Partitioning(列分區(qū))

2.4 Hash Partitioning(hash分區(qū))

2.5 KEY Partitioning(鍵值分區(qū))

2.6 subPartitioning(子分區(qū))

三汗销、優(yōu)點(diǎn)

四、分區(qū)表原理

五抵窒、分區(qū)表維護(hù)

六弛针、注意事項(xiàng)

1、單張表最多只能有1024個(gè)分區(qū)李皇,5.7版本以后可以支持8192個(gè)分區(qū)削茁,這與系統(tǒng)文件;

2掉房、如果分區(qū)字段中有主鍵或者唯一索引的列茧跋,那么所有主鍵列和唯一索引列都必須包含進(jìn)來(lái),比如

參考文檔:https://dev.mysql.com/doc/refman/5.7/en/partitioning.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末卓囚,一起剝皮案震驚了整個(gè)濱河市瘾杭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌哪亿,老刑警劉巖粥烁,帶你破解...
    沈念sama閱讀 217,084評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蝇棉,居然都是意外死亡讨阻,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)篡殷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)钝吮,“玉大人,你說(shuō)我怎么就攤上這事∑媸荩” “怎么了棘催?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,450評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)链患。 經(jīng)常有香客問(wèn)我巧鸭,道長(zhǎng)瓶您,這世上最難降的妖魔是什么麻捻? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,322評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮呀袱,結(jié)果婚禮上贸毕,老公的妹妹穿的比我還像新娘。我一直安慰自己夜赵,他們只是感情好明棍,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,370評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著寇僧,像睡著了一般摊腋。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嘁傀,一...
    開(kāi)封第一講書(shū)人閱讀 51,274評(píng)論 1 300
  • 那天兴蒸,我揣著相機(jī)與錄音,去河邊找鬼细办。 笑死橙凳,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的笑撞。 我是一名探鬼主播岛啸,決...
    沈念sama閱讀 40,126評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼茴肥!你這毒婦竟也來(lái)了坚踩?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,980評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤瓤狐,失蹤者是張志新(化名)和其女友劉穎瞬铸,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體芬首,經(jīng)...
    沈念sama閱讀 45,414評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡赴捞,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,599評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了郁稍。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赦政。...
    茶點(diǎn)故事閱讀 39,773評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出恢着,到底是詐尸還是另有隱情桐愉,我是刑警寧澤,帶...
    沈念sama閱讀 35,470評(píng)論 5 344
  • 正文 年R本政府宣布掰派,位于F島的核電站从诲,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏靡羡。R本人自食惡果不足惜系洛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,080評(píng)論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望略步。 院中可真熱鬧屉栓,春花似錦姜骡、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,713評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)捌议。三九已至纽哥,卻和暖如春背率,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背羡铲。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,852評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工蜂桶, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人犀勒。 一個(gè)月前我還...
    沈念sama閱讀 47,865評(píng)論 2 370
  • 正文 我出身青樓屎飘,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親贾费。 傳聞我的和親對(duì)象是個(gè)殘疾皇子钦购,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,689評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容