數(shù)據(jù)庫數(shù)據(jù)太多導(dǎo)致的性能問題解決方案

數(shù)據(jù)庫數(shù)據(jù)太多跑不動(dòng)怎么辦汛兜?

隨著業(yè)務(wù)的增長(zhǎng)巴粪,MySQL中保存的數(shù)據(jù)會(huì)越來越多。此時(shí)粥谬,數(shù)據(jù)庫很容易成為系統(tǒng)性能的一個(gè)瓶頸肛根,單機(jī)存儲(chǔ)容量、IO漏策、CPU處理能力都有限派哲,當(dāng)單表的數(shù)據(jù)量達(dá)到1000W或100G以后,庫表的增刪改查操作面臨著性能大幅下降的問題掺喻。

分庫分表是一種解決辦法芭届。分庫分表實(shí)際上就是對(duì)數(shù)據(jù)進(jìn)行切分。

我們一般可以將數(shù)據(jù)切分感耙,分為兩種方式:?垂直(縱向)切分和?水平(橫向)切分褂乍。

垂直切分

垂直切分常見有 垂直分庫 和 垂直分表 兩種。

1. 垂直分庫

垂直分庫就是根據(jù)業(yè)務(wù)耦合性即硼,將關(guān)聯(lián)度低的不同表存儲(chǔ)在不同的數(shù)據(jù)庫逃片。

思想與“微服務(wù)治理”類似,將系統(tǒng)拆分為多個(gè)業(yè)務(wù)只酥,每個(gè)業(yè)務(wù)使用自己?jiǎn)为?dú)的數(shù)據(jù)庫褥实。

比如下圖:

將應(yīng)用拆分為客戶、存款和貸款三個(gè)業(yè)務(wù)裂允,每個(gè)業(yè)務(wù)使用自己?jiǎn)为?dú)的數(shù)據(jù)庫损离。

2. 垂直分表

垂直分表是基于數(shù)據(jù)庫中的表字段來進(jìn)行的。業(yè)務(wù)中可能存在一些字段比較多的表绝编,表中某些字段長(zhǎng)度較大僻澎,這些長(zhǎng)字段我們又只是偶爾需要用到,這時(shí)候我們就可以考慮將表進(jìn)行垂直拆分了。

將某些不常用的怎棱,但是長(zhǎng)度又很大的字段拎出來放到另外一張表哩俭。

MySQL底層是通過數(shù)據(jù)頁存儲(chǔ)的,一條記錄占用空間過大會(huì)導(dǎo)致跨頁拳恋,造成額外的性能開銷凡资。另外數(shù)據(jù)庫以行為單位將數(shù)據(jù)加載到內(nèi)存中,這樣表中字段長(zhǎng)度較短且訪問頻率較高谬运,內(nèi)存能加載更多的數(shù)據(jù)隙赁,命中率更高,減少了磁盤IO梆暖,從而提升了數(shù)據(jù)庫性能伞访。

垂直切分例子如下圖:

我們將一張包含4個(gè)字段的表拆分為2張表,在業(yè)務(wù)代碼里面轰驳,通過字段C1來進(jìn)行關(guān)聯(lián)厚掷。

3. 垂直切分優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

不同系統(tǒng)可以使用不同的庫表,解決業(yè)務(wù)系統(tǒng)層面的耦合级解,業(yè)務(wù)清晰冒黑;

高并發(fā)場(chǎng)景下,垂直切分一定程度地提升IO勤哗、數(shù)據(jù)庫連接數(shù)抡爹,緩解單機(jī)硬件資源的瓶頸。

缺點(diǎn):

部分查詢需要在業(yè)務(wù)代碼邏輯里面做聚合芒划,增加開發(fā)復(fù)雜度冬竟;

事務(wù)處理復(fù)雜,可能需要在業(yè)務(wù)代碼層面做處理民逼;

不能根本解決單表數(shù)據(jù)量過大的問題泵殴。

水平切分

當(dāng)業(yè)務(wù)難以更細(xì)粒度地進(jìn)行垂直切分,或者切分后單表數(shù)據(jù)依然過大缴挖,存在單庫讀寫袋狞、存儲(chǔ)性能瓶頸時(shí)候,這時(shí)候就可以考慮水平切分了映屋。

水平切分又可以分為 庫內(nèi)分表 和 分庫分表苟鸯。

水平切分是根據(jù)表內(nèi)數(shù)據(jù)的內(nèi)在邏輯關(guān)系,將同一個(gè)表按不同的條件分散到多個(gè)數(shù)據(jù)庫或多個(gè)表中棚点,每個(gè)表中只包含一部分?jǐn)?shù)據(jù)早处,從而使得單個(gè)表的數(shù)據(jù)量變小,達(dá)到分布式的效果瘫析。

1. 庫內(nèi)分表

庫內(nèi)分表就是在同一個(gè)DB上砌梆,將表按照某種條件拆分為多張表默责。

比如一張訂單表,我們可以依據(jù)訂單的日期咸包,按月建表桃序。一月份的訂單放month_201901這張表,二月份的訂單放month_201902這張表烂瘫。

庫內(nèi)分表只解決單表數(shù)據(jù)量過大問題媒熊,但沒有將表分布到不同機(jī)器上,?所有請(qǐng)求還是在一臺(tái)物理機(jī)上競(jìng)爭(zhēng)cpu坟比、內(nèi)存芦鳍、IO,對(duì)于減輕mysql負(fù)載壓力來說幫助不大葛账。

2. 分庫分表

分庫分表就是將表不僅拆分柠衅,而且拆分到不同機(jī)器上。

比如我們騰訊云上的DCDB就是這種處理方法籍琳》蒲纾可以指定一張表的shardKey,然后對(duì)shardKey取hash巩割,根據(jù)hash值將數(shù)據(jù)放到不同的數(shù)據(jù)庫中裙顽,?可以解決單機(jī)物理資源的瓶頸問題付燥。

分庫分表的示例如下:

上面示例先根據(jù)業(yè)務(wù)耦合性垂直分庫宣谈,然后再針對(duì)單個(gè)庫進(jìn)行分庫分表。

3. 分庫分表優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

不存在單庫數(shù)據(jù)量過大键科、高并發(fā)的性能瓶頸闻丑,提升系統(tǒng)穩(wěn)定性和負(fù)載能力;

應(yīng)用端改造較小勋颖,不需要拆分業(yè)務(wù)模塊嗦嗡。

缺點(diǎn):

跨分片的事務(wù)一致性較難保障,一般需要一層中間件饭玲,介于業(yè)務(wù)和DB之間侥祭。對(duì)應(yīng)騰訊云上的DCDB數(shù)據(jù)庫所包含的Proxy層;

跨庫的join關(guān)聯(lián)查詢性能較差茄厘。

分庫分表帶來的問題

分庫分表能有效地緩解單機(jī)和單庫帶來的性能瓶頸和壓力矮冬,突破網(wǎng)絡(luò)IO、磁盤存儲(chǔ)次哈、CPU處理能力的瓶頸胎署,同時(shí)也帶來了一些問題。

1. 事務(wù)一致性問題

當(dāng)更新內(nèi)容同時(shí)分布在不同庫中窑滞,不可避免會(huì)帶來跨庫事務(wù)問題琼牧』煮荩跨分片事務(wù)也是分布式事務(wù),沒有簡(jiǎn)單的方案巨坊,一般可使用”XA協(xié)議”和”兩階段提交”處理撬槽。

分布式事務(wù)能最大限度保證數(shù)據(jù)庫操作的原子性,但在提交事務(wù)時(shí)需要協(xié)調(diào)多個(gè)節(jié)點(diǎn)趾撵,推后了提交事務(wù)的時(shí)間點(diǎn)恢氯,延長(zhǎng)了事務(wù)的執(zhí)行時(shí)間。導(dǎo)致事務(wù)在訪問共享資源時(shí)發(fā)生沖突或死鎖的概率增高鼓寺。隨著數(shù)據(jù)庫節(jié)點(diǎn)的增多勋拟,這種趨勢(shì)會(huì)越來越嚴(yán)重,從而成為系統(tǒng)在數(shù)據(jù)庫層面上水平擴(kuò)展的枷鎖妈候。

2. 跨節(jié)點(diǎn)關(guān)聯(lián)查詢 join 問題

切分之前敢靡,系統(tǒng)中很多列表和詳情頁所需的數(shù)據(jù)可以通過sql join來完成,而切分之后苦银,數(shù)據(jù)可能分布在不同的節(jié)點(diǎn)上啸胧,此時(shí)join帶來的問題就比較麻煩了,考慮到性能幔虏,盡量避免使用join查詢纺念。

解決這個(gè)問題的一些方法:

2.1)全局表:

全局表,也可看做是”數(shù)據(jù)字典表”想括,就是系統(tǒng)中所有模塊都可能依賴的一些表陷谱,為了避免跨庫join查詢,可以將這類表在每個(gè)數(shù)據(jù)庫中都保存一份瑟蜈。這些數(shù)據(jù)通常很少會(huì)進(jìn)行修改烟逊,所以也不擔(dān)心一致性的問題。比如騰訊云上的DCDB铺根,可以創(chuàng)建廣播表宪躯,其實(shí)就是全局表。每個(gè)節(jié)點(diǎn)都有該表的全量數(shù)據(jù)位迂,該表的所有操作都將廣播到所有物理分片(set)中访雪。

2.2)字段冗余

一種典型的反范式設(shè)計(jì),利用空間換時(shí)間掂林,為了性能而避免join查詢臣缀。例如:訂單表保存userId時(shí)候,也將userName冗余保存一份党饮,這樣查詢訂單詳情時(shí)就不需要再去查詢”買家user表”了肝陪。

但這種方法適用場(chǎng)景也有限,比較適用于依賴字段比較少的情況刑顺。而冗余字段的數(shù)據(jù)一致性也較難保證氯窍,就像上面訂單表的例子饲常,買家修改了userName后,是否需要在歷史訂單中同步更新呢狼讨?這也要結(jié)合實(shí)際業(yè)務(wù)場(chǎng)景進(jìn)行考慮贝淤。

2.3)數(shù)據(jù)組裝

在系統(tǒng)層面,分兩次查詢政供,第一次查詢的結(jié)果集中找出關(guān)聯(lián)數(shù)據(jù)id播聪,然后根據(jù)id發(fā)起第二次請(qǐng)求得到關(guān)聯(lián)數(shù)據(jù),最后將獲得到的數(shù)據(jù)進(jìn)行字段拼裝布隔。

3. 跨節(jié)點(diǎn)分頁离陶、排序、函數(shù)問題

跨節(jié)點(diǎn)多庫進(jìn)行查詢時(shí)衅檀,會(huì)出現(xiàn)limit分頁招刨、order by排序等問題。分頁需要按照指定字段進(jìn)行排序哀军,當(dāng)排序字段就是分片字段時(shí)沉眶,通過分片規(guī)則就比較容易定位到指定的分片。

當(dāng)排序字段非分片字段時(shí)杉适,就變得比較復(fù)雜了谎倔。需要先在不同的分片節(jié)點(diǎn)中將數(shù)據(jù)進(jìn)行排序并返回,然后將不同分片返回的結(jié)果集進(jìn)行匯總和再次排序猿推,最終返回給用戶片习。顯然這個(gè)過程是會(huì)降低查詢的效率,對(duì)IO彤守,CPU也會(huì)增加額外負(fù)擔(dān)毯侦。

如下圖所示:

上圖中只是取第一頁的數(shù)據(jù),對(duì)性能影響還不是很大具垫。但是如果取得頁數(shù)很大,情況則變得復(fù)雜很多试幽,因?yàn)楦鞣制?jié)點(diǎn)中的數(shù)據(jù)可能是隨機(jī)的筝蚕,為了排序的準(zhǔn)確性,需要將所有節(jié)點(diǎn)的前N頁數(shù)據(jù)都排序好做合并铺坞,最后再進(jìn)行整體的排序起宽,這樣的操作是很耗費(fèi)CPU和內(nèi)存資源的,所以頁數(shù)越大济榨,系統(tǒng)的性能也會(huì)越差坯沪。

在使用Max、Min擒滑、Sum腐晾、Count之類的函數(shù)進(jìn)行計(jì)算的時(shí)候叉弦,也需要先在每個(gè)分片上執(zhí)行相應(yīng)的函數(shù),然后將各個(gè)分片的結(jié)果集進(jìn)行匯總藻糖、再次計(jì)算淹冰,最終將結(jié)果返回。

4. 全局主鍵避重問題

在分庫分表環(huán)境中巨柒,由于表中數(shù)據(jù)同時(shí)存在不同數(shù)據(jù)庫中樱拴,主鍵平時(shí)使用的自增長(zhǎng)將無用武之地,某個(gè)分區(qū)數(shù)據(jù)庫自生成的ID無法保證全局唯一洋满。因此需要單獨(dú)設(shè)計(jì)全局主鍵晶乔,以避免跨庫主鍵重復(fù)問題。

總結(jié)

分庫分表可以解決一些問題(比如單機(jī)的IO牺勾,CPU瘪弓、磁盤瓶頸問題),但也增添了一些新問題(比如事務(wù)一致性問題禽最,跨分片join問題)腺怯。當(dāng)然隨著一些新的NewSQL技術(shù)的成熟,分庫分表這一方案也不再是業(yè)務(wù)擴(kuò)張后的最優(yōu)選擇了川无,騰訊自研云原生數(shù)據(jù)庫CynosDB就給出了更優(yōu)的解決方案呛占。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市懦趋,隨后出現(xiàn)的幾起案子晾虑,更是在濱河造成了極大的恐慌,老刑警劉巖仅叫,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件帜篇,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡诫咱,警方通過查閱死者的電腦和手機(jī)笙隙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來坎缭,“玉大人竟痰,你說我怎么就攤上這事√秃簦” “怎么了坏快?”我有些...
    開封第一講書人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)憎夷。 經(jīng)常有香客問我莽鸿,道長(zhǎng),這世上最難降的妖魔是什么拾给? 我笑而不...
    開封第一講書人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任祥得,我火速辦了婚禮兔沃,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘啃沪。我一直安慰自己粘拾,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開白布创千。 她就那樣靜靜地躺著缰雇,像睡著了一般。 火紅的嫁衣襯著肌膚如雪追驴。 梳的紋絲不亂的頭發(fā)上械哟,一...
    開封第一講書人閱讀 51,541評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音殿雪,去河邊找鬼暇咆。 笑死,一個(gè)胖子當(dāng)著我的面吹牛丙曙,可吹牛的內(nèi)容都是我干的爸业。 我是一名探鬼主播,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼亏镰,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼扯旷!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起索抓,我...
    開封第一講書人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤钧忽,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后逼肯,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體耸黑,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年篮幢,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了大刊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡洲拇,死狀恐怖奈揍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情赋续,我是刑警寧澤,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布另患,位于F島的核電站纽乱,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏昆箕。R本人自食惡果不足惜鸦列,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一租冠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧薯嗤,春花似錦顽爹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至玻褪,卻和暖如春肉渴,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背带射。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工同规, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人窟社。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓券勺,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親灿里。 傳聞我的和親對(duì)象是個(gè)殘疾皇子关炼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355