數(shù)據(jù)庫優(yōu)化不為人知道的階段
面試的時(shí)候,經(jīng)常會(huì)被面試官問到數(shù)據(jù)庫優(yōu)化方面的知識(shí)點(diǎn)。今天來總結(jié)一下數(shù)據(jù)庫優(yōu)化應(yīng)該經(jīng)過幾個(gè)階段,我覺得這樣回答是一個(gè)比較優(yōu)的答案。
0x01:SQL優(yōu)化及應(yīng)用程序優(yōu)化
一個(gè)系統(tǒng)總是從小到大,所以在系統(tǒng)還是小型系統(tǒng)的時(shí)候。首先應(yīng)該注重表的設(shè)計(jì),合理使用主鍵、外鍵、索引;字段選用合適的數(shù)據(jù)類型、合適的數(shù)據(jù)長(zhǎng)度。使用SQL考慮索引什么情況是有效的;什么時(shí)候是失效的,避免使用索引失效的SQL。
另外應(yīng)該程序優(yōu)化也很重要,比如能批量執(zhí)行SQL,就不要在程序中循環(huán)執(zhí)行SQL。使用各種框架的緩存也非常重要,例如,如果使用MyBatis時(shí),就好合理使用MyBatis的一級(jí)緩存和二級(jí)緩存;使用Hibernate時(shí),就好合理使用Hibernate的一級(jí)緩存和二級(jí)緩存等。
0x02:數(shù)據(jù)庫讀寫分類
當(dāng)業(yè)務(wù)量達(dá)到一定程度時(shí),可以考慮數(shù)據(jù)庫的讀寫分離方案,讓讀寫業(yè)務(wù)分離。但是一定要考慮如何解決寫庫與讀庫的數(shù)據(jù)一致性問題。目前,很多開源的讀寫分離服務(wù)和框架。主要基于如下兩種方案:
- 應(yīng)用程序根據(jù)業(yè)務(wù)邏輯來判斷,增刪改等寫操作命令發(fā)給寫庫,查詢命令發(fā)給讀庫。
- 利用中間件來做代理,負(fù)責(zé)對(duì)數(shù)據(jù)庫的請(qǐng)求識(shí)別出讀還是寫,并分發(fā)到不同的數(shù)據(jù)庫中。
0x03:引入緩存數(shù)據(jù)庫
NoSQL數(shù)據(jù)庫目前也是大行其道,特別Redis數(shù)據(jù)庫。例如使用Redis緩存服務(wù)器,可以把一些常用、不經(jīng)常變化的數(shù)據(jù)緩存到內(nèi)存。在內(nèi)存讀取數(shù)據(jù)的數(shù)據(jù)要比在硬盤讀取的速度不知道快多少倍。引入緩存數(shù)據(jù)庫增加了系統(tǒng)的復(fù)雜度,另外還有考慮關(guān)系型數(shù)據(jù)庫與NoSQL數(shù)據(jù)庫數(shù)據(jù)一致性的問題。
0x04:垂直拆分
一個(gè)數(shù)據(jù)庫由很多表的構(gòu)成,每個(gè)表對(duì)應(yīng)著不同的業(yè)務(wù),垂直切分是指按照業(yè)務(wù)將表進(jìn)行分類,分布到不同的數(shù)據(jù)庫上面,這樣也就將數(shù)據(jù)或者說壓力分擔(dān)到不同的庫上面,如下圖:

優(yōu)點(diǎn):
- 拆分后業(yè)務(wù)清晰,拆分規(guī)則明確
- 系統(tǒng)之間整合或擴(kuò)展容易
- 數(shù)據(jù)維護(hù)簡(jiǎn)單
缺點(diǎn):
- 部分業(yè)務(wù)表無法join,只能通過接口方式解決,提高了系統(tǒng)復(fù)雜度
- 受每種業(yè)務(wù)不同的限制存在單庫性能瓶頸,不易數(shù)據(jù)擴(kuò)展跟性能提高
- 事務(wù)處理復(fù)雜
0x05:水平拆分
垂直拆分后遇到單機(jī)瓶頸,可以使用水平拆分。相對(duì)于垂直拆分的區(qū)別是:垂直拆分是把不同的表拆到不同的數(shù)據(jù)庫中,而水平拆分是把同一個(gè)表拆到不同的數(shù)據(jù)庫中。
相對(duì)于垂直拆分,水平拆分不是將表的數(shù)據(jù)做分類,而是按照某個(gè)字段的某種規(guī)則來分散到多個(gè)庫之中,每個(gè)表中包含一部分?jǐn)?shù)據(jù)。簡(jiǎn)單來說,我們可以將數(shù)據(jù)的水平切分理解為是按照數(shù)據(jù)行的切分,就是將表中 的某些行切分到一個(gè)數(shù)據(jù)庫,而另外的某些行又切分到其他的數(shù)據(jù)庫中,主要有分表,分庫兩種模式。如下圖:

分庫模式

分表模式
優(yōu)點(diǎn):
- 不存在單庫大數(shù)據(jù),高并發(fā)的性能瓶頸
- 對(duì)應(yīng)用透明,應(yīng)用端改造較少
- 按照合理拆分規(guī)則拆分,join操作基本避免跨庫
- 提高了系統(tǒng)的穩(wěn)定性跟負(fù)載能力
缺點(diǎn):
- 拆分規(guī)則難以抽象
- 分片事務(wù)一致性難以解決
- 數(shù)據(jù)多次擴(kuò)展難度跟維護(hù)量極大
- 跨庫join性能較差