MySQL 數(shù)據(jù)存儲 / 索引 / 事務(wù)隔離級別 / 主從復(fù)制 / 分庫分表

?數(shù)據(jù)存儲引擎

存儲引擎是 MYSQL 的核心技術(shù),不同的存儲引擎使用不同的存儲機制姿搜、索引技巧笤昨、鎖定水平并最終提供不同的功能和能力。常見的引擎分為三種:InnoDB 存儲引擎(MYSQL 默認的事務(wù)性引擎)停士、MyISAM 存儲引擎挖帘、Memory 存儲引擎完丽。三種存儲引擎的功能對比如下表所示:

總結(jié)三種引擎的使用選擇如下

InnoDB:適合要提供提交、回滾和崩潰后的安全恢復(fù)的事務(wù)安全能力拇舀,并要求實現(xiàn)并發(fā)控制逻族;

MyISAM:適合于只讀的數(shù)據(jù),或者表比較小骄崩、可以忍受修復(fù)操作數(shù)據(jù)庫聘鳞;

Memory:適用于快速查找數(shù)據(jù),用于數(shù)據(jù)分析中產(chǎn)生的中間數(shù)據(jù)要拂。


數(shù)據(jù)庫三大范式? ?java初學(xué)者組團學(xué)習(xí):737251827

第一范式:數(shù)據(jù)庫表的每一列都是不可分割的基本數(shù)據(jù)項抠璃,即同一列不能有多個值;

第二范式:在第一范式的基礎(chǔ)上脱惰,非主鍵列完全依賴于主鍵搏嗡,而不能是依賴于主鍵的一部分。如:設(shè)計訂單信息表時枪芒,商品名稱彻况、商品價格等商品信息與表的主鍵不相關(guān),而只與商品編號相關(guān)舅踪,因此可將表設(shè)計為訂單信息表和商品信息表纽甘。

第三范式:在第二范式的基礎(chǔ)上,非主鍵列只依賴于主鍵抽碌,不依賴于其他非主鍵悍赢。如果一張表中出現(xiàn)另一張表的非主鍵,可以將這兩張表用外鍵關(guān)聯(lián)货徙,而不是將另一張表的非主鍵直接寫在當(dāng)前表中左权。設(shè)計數(shù)據(jù)庫表的時候,要盡量遵守三范式痴颊,如果不遵守赏迟,必須有足夠的理由。


數(shù)據(jù)庫索引類型及原理

索引是一種對數(shù)據(jù)庫表中一列或多列的值進行排序的一種數(shù)據(jù)結(jié)構(gòu)蠢棱,指向表中特定的數(shù)據(jù)內(nèi)容锌杀,從而提高查詢效率。


一泻仙、為什么要用索引

假設(shè)有一張存儲了 10 萬個數(shù)據(jù)(每條數(shù)據(jù)包含姓名糕再、年齡、身份證號等信息)的表玉转,若沒有索引突想,要想查找姓名為"張三”的身份信息,需要從上到下依次對表中的所有數(shù)據(jù)進行掃描,找到所有名為張三的數(shù)據(jù)猾担,這也叫全表查詢袭灯。

可以看出,全表查詢的效率非常低绑嘹,需要逐條對比妓蛮,因此就需要通過對每條數(shù)據(jù)建立索引,從而直接通過索引快速查詢到數(shù)據(jù)信息圾叼,大大提高了查詢效率。


二捺癞、數(shù)據(jù)庫索引的類型及原理

1夷蚊、B+樹索引:適合范圍查詢、順序查詢髓介,不適合插入惕鼓、刪除數(shù)據(jù),是 InnoDB唐础、MyISAM 的索引方式箱歧。

B 樹與 B+樹都是用于大量數(shù)據(jù)查詢的一種數(shù)據(jù)結(jié)構(gòu),二者有以下特點:

B 樹:

由二叉搜索轉(zhuǎn)變?yōu)?N 叉搜索一膨,樹的高度大大降低呀邢,查詢次數(shù)少;

葉子節(jié)點豹绪、非葉子節(jié)點都可以存儲多個數(shù)據(jù)价淌,每次可以讀取一頁數(shù)據(jù),IO 次數(shù)更少瞒津;

通過中序遍歷蝉衣,可以訪問樹上所有節(jié)點,但需要多次往返各個節(jié)點之間巷蚪,效率有待提升病毡;

由 B 樹的特點可知,對于范圍查詢而言屁柏,B 樹需要通過中序遍歷來進行查找啦膜,不夠完美,B+樹在此基礎(chǔ)上進行了改進前联。

B+樹的特點為:

依舊為 N 叉樹功戚,但是非葉子只保存索引不存儲數(shù)據(jù),所有數(shù)據(jù)存儲在同一層的葉子節(jié)點上似嗤,查詢性能更穩(wěn)定啸臀;

非葉子節(jié)點可保存更多索引,相同的數(shù)據(jù),B+樹的高度更低乘粒,查詢的 IO 次數(shù)更少豌注;

所有葉子節(jié)點形成一個有序鏈表,不需要通過中序遍歷進行順序查詢灯萍,更適合范圍查詢轧铁。

對比可知,B+樹最大的優(yōu)點就是適合范圍查詢旦棉,這在實際應(yīng)用中是非常廣泛的齿风,因此 InnoDB 選用的就是 B+Tree。B+樹的缺點就是插入绑洛、刪除操作非常復(fù)雜救斑,一般只用在數(shù)據(jù)庫的查詢操作中。


2真屯、哈希索引:適合單一數(shù)據(jù)的查找脸候、刪除、插入绑蔫,不適合范圍查找运沦,是 Memory 的索引方式。

哈希表的查詢配深、刪除携添、插入的平均時間復(fù)雜度都是 O(1),適合每次只查詢一條信息凉馆。但是對于需要排序查詢(對查詢的數(shù)據(jù)進行排序輸出)薪寓、范圍查詢(如:大于或小于某值的范圍查詢),采用哈希索引的時間復(fù)雜度會從 O(1)退化為 O(n)澜共,相當(dāng)于全表查詢向叉,效率極低∴露總結(jié)哈希索引的特點如下:

只支持等值比較查詢母谎,不支持范圍查詢;

訪問數(shù)據(jù)的速度非尘└铮快奇唤,但當(dāng)哈希沖突較多時,查詢效率會大大降低匹摇;

哈希索引數(shù)據(jù)不是按順序存儲的咬扇,即無序的,無法用于排序查詢廊勃。因此懈贺,哈希索引只適用于特定的場合经窖,不要輕易使用。


三梭灿、索引分類

1画侣、聚簇索引:葉子節(jié)點存儲整行數(shù)據(jù)

按照每張表的主鍵構(gòu)造一顆 B+樹,葉子節(jié)點存放整張表的行數(shù)據(jù)堡妒。每張表只能有一個聚簇索引配乱,如果沒有主鍵,InnoDB 會選擇非空的唯一索引代替皮迟。如果沒有這樣的索引搬泥,InnoDB 會隱式的定義一個主鍵來作為聚簇索引。

優(yōu)點:

索引和數(shù)據(jù)保存在同一顆 B+樹中伏尼,數(shù)據(jù)訪問更快佑钾;

聚簇索引對于主鍵的范圍查找速度非常快烦粒。


2、非聚簇索引(輔助索引):葉子節(jié)點存儲主鍵值

在聚簇索引之上創(chuàng)建的索引稱之為非聚簇索引代赁,其葉子節(jié)點存儲的數(shù)據(jù)為主鍵值扰她,訪問數(shù)據(jù)通常需要二次查找。

假設(shè)一張表中有 id(主鍵)芭碍,order_id(唯一鍵)兩個字段徒役。若使用“where id=14"的條件進行查詢,就會走聚簇索引窖壕,直接可以查詢出對應(yīng)行數(shù)據(jù)忧勿;若使用“where order_id= 1100202"的條件進行查詢,就會走非聚簇索引瞻讽,會先根據(jù) order_id 查詢到所在行的主鍵 id鸳吸,再根據(jù)主鍵 id 走聚簇索引就查到行數(shù)據(jù)。如下圖所示:

回表與覆蓋索引

所謂回表查詢速勇,就是先通過非聚簇索引定位到主鍵晌砾,再通過聚簇索引定位到數(shù)據(jù)行。

索引覆蓋則是一種避免回表查詢的優(yōu)化策略烦磁,即:一個索引包含了所有需要查詢的字段值养匈,查詢時直接返回索引的數(shù)據(jù),而不需要回表查詢都伪。

舉例:假設(shè)在學(xué)生表的年齡上建立了索引呕乎,那么當(dāng)進行 select age from student_table where age < 20 的查詢時,在索引的葉子節(jié)點上陨晶,已經(jīng)包含了 age 信息猬仁,不會再次進行回表查詢。

覆蓋索引的優(yōu)點:

覆蓋索引只需要讀取索引,極大減小了數(shù)據(jù)訪問量逐虚;

避免了回表查詢聋溜,提高了查詢效率。


四叭爱、索引失效的情況

五撮躁、聯(lián)合索引最左前綴匹配原則

最左前綴匹配:最左優(yōu)先,以最左邊為起點的任何連續(xù)的索引都可以匹配上买雾。遇到范圍查詢(>把曼、<、between漓穿、like)就會停止匹配嗤军。

假設(shè)有聯(lián)合索引(a,b,c):

where 條件為(a,b,c)、(b,a,c)晃危、(c,a,b)等叙赚,會走聯(lián)合索引;

where 條件為(a)僚饭、(a,b)震叮、(a,b,c),會走聯(lián)合索引鳍鸵;

where 條件為(b)苇瓣、(c)、(b,c)偿乖,不會走索引击罪,會全表掃描;

where 條件為(a,c)時贪薪,會走索引媳禁,但只使用 a 的索引。

為什么要遵循最左匹配原則

假設(shè)有如下 B+樹画切,聯(lián)合索引為(a,b):

由圖可知损话,最左邊的 a 都是有序的,分別是 : 1槽唾、1丧枪、2、2庞萍、3拧烦、3, 但是右邊的 b 不一定有序: 1钝计、2恋博、1齐佳、4、3债沮、2炼吴。但是在 a 相同的情況下 b 是有序的, 如: a=1 時 b =1疫衩,2 硅蹦; a=2 時, b= 1闷煤,4童芹; a=3 時 ,b=1鲤拿,2假褪。

因此,在篩選數(shù)據(jù)的時候近顷, 若直接篩選 b 生音,整個就是無序的,需要做全表掃描窒升,此時索引失效久锥;若先篩選 a 再篩選 b ,就可以利用 B+樹的有序性來加快查找速度异剥。綜上,在使用聯(lián)合索引時需要遵循最左匹配原則絮重。


六冤寿、創(chuàng)建索引的原則

1. 遵循最左前綴匹配原則

為頻繁作為查詢條件的字段創(chuàng)建索引(如:訂單 id)

更新頻繁的字段不適合創(chuàng)建索引(如:訂單狀態(tài))

不能有效區(qū)分數(shù)據(jù)或重復(fù)值比較多的字段不適合創(chuàng)建索引(如:性別)

盡量拓展索引,不要新建索引青伤。

定義有外鍵的字段一定要創(chuàng)建索引督怜。

(外鍵:一個表中存放的另一個表的主鍵。)

當(dāng)多個用戶對數(shù)據(jù)庫并發(fā)操作時狠角,會存在數(shù)據(jù)讀取不一致的問題号杠,造成數(shù)據(jù)混亂。數(shù)據(jù)庫中鎖的作用就是保證數(shù)據(jù)的一致性丰歌,與線程同步含義相同姨蟋。數(shù)據(jù)庫中的鎖分為兩大類:悲觀鎖和樂觀鎖。

悲觀鎖(Pessimistic Lock) :適用于多寫的應(yīng)用類型

總是假設(shè)最壞的情況立帖,每次有事務(wù)去拿數(shù)據(jù)時都會覺得別人會修改眼溶,所以每次使用時都會給該數(shù)據(jù)上鎖,而其他事務(wù)就會阻塞晓勇,直到這個事務(wù)釋放鎖把數(shù)據(jù)轉(zhuǎn)讓給下一個用戶堂飞。

悲觀鎖按使用性質(zhì)可劃分為以下幾類:

共享鎖(Share Lock):也叫讀鎖(S 鎖)灌旧,允許多個事務(wù)對同一數(shù)據(jù)共享一把鎖,都能訪問到數(shù)據(jù)绰筛,但 只能讀不能修改枢泰。

排他鎖(Exclusive Lock):也叫寫鎖(X 鎖),一個事務(wù)獲取了某數(shù)據(jù)的排他鎖铝噩,其它事務(wù)就不能獲取其它鎖衡蚂,只有獲取排他鎖的事務(wù)能對數(shù)據(jù)進行讀取和修改。(獨占式鎖)

更新鎖:簡稱 U 鎖薄榛,在數(shù)據(jù)修改操作的初始化階段鎖定可能要被修改的資源讳窟,從而避免共享鎖競爭排他鎖造成的死鎖現(xiàn)象。

悲觀鎖按作用范圍可劃分為:

行鎖:鎖的作用范圍是行級別敞恋。對于 UPDATE丽啡、INSERT、DELETE 語句硬猫,會自動加排他鎖补箍。InnoDB 默認采用行鎖。 數(shù)據(jù)庫能夠確對哪些行進行操作的情況下使用行鎖(如使用主鍵時)啸蜜,如果不知道就使用表鎖(不使用主鍵時)坑雅。

行鎖的優(yōu)勢:鎖的粒度小,發(fā)生鎖沖突的概率低衬横,并發(fā)處理的能力高裹粤。

行鎖的劣勢:開銷大,加鎖慢蜂林。


2遥诉、表鎖:鎖的作用范圍是整張表。表鎖的優(yōu)勢:開銷小噪叙,加鎖快矮锈。表鎖的劣勢:鎖的粒度大,發(fā)生鎖沖突的概率高睁蕾,并發(fā)處理的能力低苞笨。

樂觀鎖(Optimistic Lock):適用于多讀的應(yīng)用類型

與悲觀鎖相反,總是假設(shè)最好的情況子眶,每次有事務(wù)去拿數(shù)據(jù)的時候都認為別人不會修改瀑凝,所以不會給該數(shù)據(jù)上鎖。但在更新的時候會判斷在此期間有沒有事務(wù)更新了該數(shù)據(jù)臭杰。樂觀鎖兩種常見的實現(xiàn)方式:

版本號機制:一般是在數(shù)據(jù)表中加上一個數(shù)據(jù)版本號 version 字段猜丹,表示數(shù)據(jù)被修改的次數(shù),當(dāng)數(shù)據(jù)被修改時硅卢,version 值會加一射窒。當(dāng)線程 A 要更新數(shù)據(jù)值時藏杖,在讀取數(shù)據(jù)的同時也會讀取 version 值,在提交更新時脉顿,若剛才讀取到的 version 值為當(dāng)前數(shù)據(jù)庫中的 version 值相等時才更新蝌麸,否則重試更新操作,直到更新成功艾疟。

CAS 算法(compare and swap):一種無鎖算法来吩,即在不使用鎖的情況下實現(xiàn)多線程之間的變量同步。CAS 采用自旋的模式蔽莱,會浪費 CPU 資源弟疆。原理:通過原子操作來更新數(shù)據(jù)的值的,比較讀取的當(dāng)前值 V 與當(dāng)前線程先前取出的值 A 是否一樣盗冷,若一樣表示該值在此期間未被其它線程修改怠苔,則更新該值,否則重新從數(shù)據(jù)表讀取數(shù)據(jù)賦給 A仪糖,再進行 V 和 A 的比較柑司,直到更新成功。


數(shù)據(jù)庫事務(wù)隔離級別

事務(wù)就是訪問數(shù)據(jù)庫進行的一組數(shù)據(jù)操作锅劝,所有操作必須成功攒驰,否則就會回滾所有操作導(dǎo)致失敗。

一故爵、事務(wù)的四大特性(ACID)

原子性(Atomicity):事務(wù)開始后的所有操作要么全部完成玻粪,要么全部不完成,不能只完成一部分诬垂。事務(wù)執(zhí)行過程中發(fā)生錯誤劲室,會回滾已有操作并恢復(fù)到事務(wù)開始前的狀態(tài)。

一致性(Consistency):事務(wù)開始前和結(jié)束后剥纷,數(shù)據(jù)庫的完整性沒有被破壞。比如:A 向 B 轉(zhuǎn)賬 1000 元呢铆,A 的賬戶中會減少 1000 元晦鞋,而 B 的賬戶中會增加 1000 元。

隔離性(Isolation):多個事務(wù)并發(fā)執(zhí)行時棺克,同一時間只允許一個事務(wù)請求同一數(shù)據(jù)悠垛,不同的事務(wù)之前不會互相干擾。如:A 在從一張銀行卡取款的過程中娜谊,其他人不能向這張銀行卡轉(zhuǎn)賬确买。

持久性(Durability):事務(wù)完成之后,事務(wù)對數(shù)據(jù)庫的所有更改應(yīng)該保存在數(shù)據(jù)庫中纱皆,不能回滾湾趾。


二芭商、事務(wù)并發(fā)的三大問題

臟讀:一個事務(wù)讀取到了另一個事務(wù)未提交的數(shù)據(jù)。比如:事務(wù) A 讀取了事務(wù) B 更新但尚未提交的數(shù)據(jù)搀缠,B 提交失敗發(fā)生回滾操作铛楣,那么 A 讀取的數(shù)據(jù)是臟數(shù)據(jù)。

不可重復(fù)讀:一個事務(wù)多次讀取同一數(shù)據(jù)艺普,另一事務(wù)在其讀取過程中對該數(shù)據(jù)進行了修改(update 操作)并提交簸州,導(dǎo)致這個事務(wù)前后讀取的數(shù)據(jù)結(jié)果不一致。

幻讀:一個事務(wù)多次讀取同一數(shù)據(jù)歧譬,另一事務(wù)在其讀取過程中對該數(shù)據(jù)進行了插入或刪除(insert 操作)并提交岸浑,導(dǎo)致這個事務(wù)前后讀取的數(shù)據(jù)結(jié)果不一致。


三瑰步、事務(wù)隔離級別及實現(xiàn)原理

事務(wù)隔離是通過加鎖來實現(xiàn)的矢洲,鎖的競爭會帶來性能的損失。事務(wù)隔離級別分為以下四種:

讀未提交(READ UNCOMMITTED):不加鎖面氓,性能最好玉工,但是無法解決臟讀、不可重復(fù)讀邪意、幻讀問題忘蟹;實現(xiàn):不加鎖,可看作無隔離呻拌。

讀提交(READ COMMITTED):一個事務(wù)只能讀取其它事務(wù)已經(jīng)提交的數(shù)據(jù)葱轩,但不能解決不可重復(fù)讀、幻讀問題藐握;實現(xiàn):事務(wù)每次操作數(shù)據(jù)時都會重新生成一次快照靴拱,來記錄當(dāng)前數(shù)據(jù)的版本,在快照時間之前提交的數(shù)據(jù)版本則可以被讀到猾普。(MVCC)

可重復(fù)讀(REPEATABLE READ):一個事務(wù)在開始后直到提交前的任意時刻讀取的數(shù)據(jù)都是一樣的袜炕,不會讀到其它事務(wù)對已有數(shù)據(jù)的修改,但可以讀取其它事務(wù)插入的新數(shù)據(jù)初家,即無法解決幻讀問題偎窘。(mysql 中默認的隔離級別,MVCC)實現(xiàn):事務(wù)開始時生成一個當(dāng)前事務(wù)全局性的快照溜在,后面每次讀取的數(shù)據(jù)都是該次快照的數(shù)據(jù)版本陌知。

串行化(SERIALIZABLE):隔離效果就好,可以解決臟讀掖肋、不可重復(fù)讀仆葡、幻讀問題,但需要加鎖志笼,性能較差沿盅。實現(xiàn):一個事務(wù)讀的時候會加共享鎖把篓,其他事務(wù)可以并發(fā)讀,但不能寫嗡呼;該事務(wù)寫的時候加排它鎖纸俭,其他事務(wù)不能寫也不能讀。

MVCC(多版本并發(fā)控制)實現(xiàn)機制

MVCC 是一種多版本并發(fā)控制機制南窗,通過保存數(shù)據(jù)在某個時間點的快照來實現(xiàn)的揍很。不同的存儲引擎的 MVCC 實現(xiàn)是不同的,典型的有樂觀(Optimistic)并發(fā)控制和悲觀(pessimistic)并發(fā)控制万伤。

InnoDB 的 MVCC窒悔,是通過在每行記錄后面保存兩個隱藏的列來實現(xiàn)的。這兩個列敌买,一個保存了行的創(chuàng)建時間(創(chuàng)建版本號)简珠,一個保存行的刪除時間(刪除版本號)。每開始一個新的事務(wù)虹钮,系統(tǒng)版本號都會自動遞增聋庵。事務(wù)開始時刻的系統(tǒng)版本號會作為事務(wù)版本號,用來和查詢到的每行記錄的版本號進行比較芙粱。保存這兩個額外的系統(tǒng)版本號祭玉,使大多數(shù)讀操作都可以不用加鎖。這樣設(shè)計使得讀數(shù)據(jù)操作簡單春畔,性能好脱货。不足之處就是每行記錄都需要額外的存儲空間,需要更多的行檢查和維護工作律姨。

在 READ COMMITTED 隔離級別下振峻,一個事務(wù)多次輸入 SELECT 查找語句時,InnoDB 每次查詢時都會生成一個快照择份,記錄當(dāng)前已提交的數(shù)據(jù)版本扣孟,在這之前的數(shù)據(jù)版本都可以被讀取到。

在 REPEATABLE READ 隔離級別下荣赶,一個事務(wù)多次輸入 SELECT 查找語句時凤价,InnoDB 只在事務(wù)開始時生成一個當(dāng)前事務(wù)全局性的快照,每次查找都是讀取早于當(dāng)前事務(wù)版本的數(shù)據(jù)行讯壶。


MySQL 數(shù)據(jù)庫性能優(yōu)化的方法

硬件優(yōu)化料仗。提升服務(wù)器的硬件配置湾盗,如 CPU伏蚊、內(nèi)存大小等。

數(shù)據(jù)庫調(diào)優(yōu)格粪,如增加索引躏吊。

引入緩存氛改,減小數(shù)據(jù)庫壓力。

讀寫分離比伏。增加從庫胜卤,抗住更多的讀請求。

分庫分表赁项。單表數(shù)據(jù)超千萬時葛躏,考慮分庫分表。

MySQL 主從復(fù)制悠菜,讀寫分離


一舰攒、為什么要主從復(fù)制

高可用性:若主庫發(fā)生故障,可快速切換到其中一個從庫悔醋,從而保證系統(tǒng)業(yè)務(wù)的可用性摩窃。

負載均衡:主庫用于寫數(shù)據(jù),各個從庫用于讀數(shù)據(jù)芬骄,實現(xiàn)讀寫分離猾愿,將流量分布到各個庫上,從而實現(xiàn)負載均衡账阻。

可擴展性好:當(dāng)業(yè)務(wù)量很大的時候蒂秘,為了抗住更多的讀請求,可以增加從庫宰僧,從而分擔(dān)流量材彪。


二、主從復(fù)制的原理

MySQL 主從復(fù)制是一個異步的復(fù)制過程琴儿,主庫發(fā)送更新事件到從庫段化,從庫讀取更新記錄,并執(zhí)行更新記錄造成,使得從庫的內(nèi)容與主庫保持一致显熏。

主從復(fù)制的流程為:

當(dāng)主庫進行 insert、update晒屎、delete 操作時喘蟆,會按順序?qū)懭氲?binlog(二進制日志)中;

從庫啟動 I/O 線程鼓鲁,跟主庫建立客戶端連接蕴轨;

主庫啟動 binlog dump 線程,讀取主庫上 binlog 的內(nèi)容發(fā)送給從庫的 I/O 線程骇吭;

從庫的 I/O 線程接收到 binlog 內(nèi)容后橙弱,將內(nèi)容寫入到本地的 relay log(中繼日志);

從庫啟動 SQL 線程,讀取 relay log 的內(nèi)容棘脐,并完成對從庫數(shù)據(jù)的更新斜筐。

上圖為一個從庫的流程,實際中蛀缝,有 N 個從庫顷链,主庫就會對應(yīng)有 N 個 binlog dump 線程,而每個從庫都會有自己的 I/O 線程和 SQL 線程屈梁。


MySQL 分庫分表

一嗤练、為什么要分庫分表

MySQL 單表最多能存儲 5000w 數(shù)據(jù),但是單表數(shù)據(jù)表達 1000w 以后在讶,即使添加從庫潭苞、優(yōu)化索引,查詢的性能依舊很差真朗。這時候就需要通過分庫分表此疹,從而有效減小單臺數(shù)據(jù)庫的壓力。

二遮婶、數(shù)據(jù)表的兩種拆分方式

1蝗碎、垂直拆分

數(shù)據(jù)表列的拆分,把一張列比較多的表拆分為多張表旗扑,如:把主鍵和常用的列放一張表蹦骑,把主鍵和不常用的列放另一張表。如下圖所示:

垂直拆分還有一種理解臀防,即從業(yè)務(wù)的角度進行拆分眠菇,如:一個數(shù)據(jù)中既存在用戶表,又存在訂單表袱衷,那么就可以把用戶表存在用戶庫捎废,訂單表存在訂單庫中。如下圖所示:

優(yōu)點:使每條數(shù)據(jù)變小致燥,一個數(shù)據(jù)塊 block 可以存儲更多數(shù)據(jù)登疗,查詢時可減小 I/O 次數(shù);

缺點:

主鍵出現(xiàn)冗余嫌蚤,需要管理冗余列辐益,查詢所有數(shù)據(jù)時需要關(guān)聯(lián)查詢 JOIN 操作;

依舊會出現(xiàn)單表數(shù)據(jù)量過大的情況脱吱。

應(yīng)用場景:數(shù)據(jù)表中某些列常用智政,而某些列不常用的情況。


2箱蝠、水平拆分

數(shù)據(jù)表行的拆分续捂,數(shù)據(jù)數(shù)量超過千萬級別時猜年,數(shù)據(jù)表的查詢效率就會很慢,就可以把一張表的數(shù)據(jù)按行拆分成多個表來存放疾忍。如下圖所示:

優(yōu)點:不存在單表大數(shù)據(jù)造成的性能瓶頸;

缺點:邏輯復(fù)雜床三,通常查詢時需要多個表名一罩;

應(yīng)用場景:單表數(shù)據(jù)量達百萬級別甚至千萬級別。

上圖所示為庫內(nèi)分表撇簿,僅僅單純的解決了單一表數(shù)據(jù)過大的問題聂渊,而沒有把表的數(shù)據(jù)分布到不同的機器上,因此對于減輕 MySQL 服務(wù)器的壓力來說四瘫,并沒有太大的作用汉嗽,大家還是競爭同一個物理機上的 IO、CPU找蜜、網(wǎng)絡(luò)饼暑,這個就要通過分庫來解決,即分庫分表洗做。


三弓叛、數(shù)據(jù)表水平拆分的兩種方案

水平分表最主要的就是路由算法,即把路由的 key 按照指定的算法進行路由存放诚纸。常用的水平分表方案有兩種:range 范圍路由撰筷、hash 路由。

1畦徘、range 范圍路由:按照數(shù)據(jù)范圍進行拆分數(shù)據(jù)

range 方案比較簡單毕籽,就是把一定范圍內(nèi)的訂單,存放到一個表中井辆;如上圖 id=12 放到 0 表中关筒,id=1300 萬的放到 1 表中。設(shè)計這個方案時就是前期把表的范圍設(shè)計好杯缺。通過 id 進行路由存放平委。

優(yōu)點:數(shù)據(jù)擴容方便,不需要數(shù)據(jù)遷移夺谁;

缺點:有熱點問題廉赔,由于 id 的值一般遞增的,某段時間的數(shù)據(jù)會集中在某一張表中匾鸥,就會導(dǎo)致該表壓力過大蜡塌,而其它表沒有壓力。(熱點問題是指某段時間對數(shù)據(jù)的操作集中在一個表中勿负,而其他表的操作很少馏艾。)

2劳曹、hash 路由:指定路由 key 對分表總數(shù)進行取模

在設(shè)計系統(tǒng)之前,假設(shè)未來幾年的訂單量為 4000 萬琅摩。每張表我們可以容納 1000 萬铁孵,也我們可以設(shè)計 4 張表進行存儲。

hash 路由的具體方法為:對指定的路由 key(如:id)對分表總數(shù)進行取模房资,上圖中蜕劝,id=12 的訂單,對 4 進行取模轰异,也就是會得到 0岖沛,那此訂單會放到 0 表中。id=13 的訂單搭独,取模得到為 1婴削,就會放到 1 表中。為什么對 4 取模牙肝,是因為分表總數(shù)是 4唉俗。

優(yōu)點:數(shù)據(jù)可以均勻的放到每張表中,對數(shù)據(jù)進行操作時配椭,就不會有熱點問題互躬。

缺點:若數(shù)據(jù)量繼續(xù)增大,需要增加分表數(shù)颂郎,數(shù)據(jù)的遷移和擴容吼渡,很會麻煩。


四乓序、分庫分表方案

上述的兩種水平分表方案中寺酪,hash 可以解決數(shù)據(jù)均勻問題,range 可以解決數(shù)據(jù)遷移問題替劈,因此可以將兩者結(jié)合在一起寄雀,實現(xiàn)分庫分表的方案。

實現(xiàn)思路為:先用 range 路由方案讓數(shù)據(jù)落地到一個范圍內(nèi)陨献,這樣需要擴容時以前的數(shù)據(jù)不需要遷移盒犹;再在這個范圍內(nèi),使用 hash 路由方案讓數(shù)據(jù)均勻分配在幾個表中眨业,這樣就解決了數(shù)據(jù)熱點問題急膀,保證每個表壓力一樣;最后把這些表分配到幾臺數(shù)據(jù)庫機器上龄捡,實現(xiàn)分庫卓嫂。以上就實現(xiàn)了分庫分表

具體實現(xiàn)聘殖,我們一起看一個例子:

假設(shè)數(shù)據(jù)量為 4000 萬晨雳,定義一個 Group01 組行瑞,組內(nèi)有三個 DB 庫,DB_0 中有 4 張表餐禁,DB_1 中有 3 張表血久,DB_2 中有 3 張表。每張表內(nèi)存儲的路由 key(id)的范圍如上圖所示帮非。這里假設(shè) DB_0 的服務(wù)器性能更好氧吐,所以存儲 4 張表,從而可以存儲更多的數(shù)據(jù)喜鼓。

存儲路由 key 的具體流程為:

擴容的時候,只需要新增加一個 group02 組衔肢,而不需要遷移之前的數(shù)據(jù)庄岖。

實際設(shè)計的時候,我們只需要維護 group角骤、db隅忿、table 的對應(yīng)關(guān)系,就可以將數(shù)據(jù)存儲在對應(yīng)的表中邦尊。如下圖所示背桐,圖中 table 表字段有些小錯誤,僅做示例蝉揍。


實際開發(fā)的時候链峭,這三張表可以保存在緩存,而不是 MySQL 中又沾。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末弊仪,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子杖刷,更是在濱河造成了極大的恐慌励饵,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件滑燃,死亡現(xiàn)場離奇詭異役听,居然都是意外死亡,警方通過查閱死者的電腦和手機表窘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門典予,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人乐严,你說我怎么就攤上這事熙参。” “怎么了麦备?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵孽椰,是天一觀的道長昭娩。 經(jīng)常有香客問我,道長黍匾,這世上最難降的妖魔是什么栏渺? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮锐涯,結(jié)果婚禮上磕诊,老公的妹妹穿的比我還像新娘。我一直安慰自己纹腌,他們只是感情好霎终,可當(dāng)我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著升薯,像睡著了一般莱褒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上涎劈,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天广凸,我揣著相機與錄音,去河邊找鬼蛛枚。 笑死谅海,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蹦浦。 我是一名探鬼主播扭吁,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼盲镶!你這毒婦竟也來了智末?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤徒河,失蹤者是張志新(化名)和其女友劉穎系馆,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體顽照,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡由蘑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了代兵。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片尼酿。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖植影,靈堂內(nèi)的尸體忽然破棺而出裳擎,到底是詐尸還是另有隱情,我是刑警寧澤思币,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布鹿响,位于F島的核電站羡微,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏惶我。R本人自食惡果不足惜妈倔,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望绸贡。 院中可真熱鬧盯蝴,春花似錦、人聲如沸听怕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽尿瞭。三九已至闽烙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間筷厘,已是汗流浹背鸣峭。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工宏所, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留酥艳,地道東北人。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓爬骤,卻偏偏與公主長得像充石,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子霞玄,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,901評論 2 345

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