溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何從設(shè)計和規(guī)范上規(guī)避RDS性能問題?

發(fā)布時間:2020-08-10 03:37:23 來源:ITPUB博客 閱讀:150 作者:tianxiaoxu 欄目:數(shù)據(jù)庫

【本文轉(zhuǎn)自云棲社區(qū) 作者neo.Wang】
在初創(chuàng)型互聯(lián)網(wǎng)公司中,開發(fā)們整天想的唯一一件事,就是“把功能做出來”。而當(dāng)公司業(yè)務(wù)量逐漸上漲、甚至翻了好幾番之后,最開始的程序上的問題,就一個接一個地暴露了出來。
其中,最明顯的,就是數(shù)據(jù)庫的壓力問題。下文提到的數(shù)據(jù)庫,都指RDS for MYSQL

場景一:寬表

現(xiàn)象

開發(fā)在設(shè)計表結(jié)構(gòu)的時候,很大程度上是在參考產(chǎn)品原型的設(shè)計。通常會把產(chǎn)品原型中,需要一起查詢的條件、一起展示的字段,都放在同一張表中。而互聯(lián)網(wǎng)公司的產(chǎn)品迭代又是非??斓?,新功能層出不窮,開發(fā)沒有時間重新梳理數(shù)據(jù)庫結(jié)構(gòu),就盲目地在原來的表上增加冗余字段,為了使功能盡快開發(fā)完成。這就使得某些“老古董”的表,越來越寬,七八十個字段以上的大寬表越來越多。

建議

(1)單個InnoDB表的字段數(shù),建議少于50個;
(2)大字段,例如:text、blob類型,考慮單獨存放;

場景二:列表的行數(shù)查詢

現(xiàn)象

在后臺或者部分前端的功能中,常常會出現(xiàn)類似MIS系統(tǒng)的列表查詢功能。一般這種功能,都是按照選定的查詢條件,先查出行數(shù),再按照分頁規(guī)則查詢出第一頁的數(shù)據(jù)。于是,就出現(xiàn)了這樣的幾種情況:
(1)查詢列表明細(xì),是需要使用多表關(guān)聯(lián)查詢的。開發(fā)為了方便,直接把這個查詢明細(xì)的“多表關(guān)聯(lián)”的SQL拿過來,把select后邊的字段改成count(*),就直接作為查詢行數(shù)的SQL,甚至連order by都不去掉。而從業(yè)務(wù)上來說,查詢行數(shù)的時候,只需要查詢其中一張表就可以了;
(2)代碼邏輯的設(shè)計不合理,導(dǎo)致某些開發(fā),直接套用“首頁”邏輯,查詢后續(xù)每一頁的時候,都重新查詢了一遍行數(shù);

建議

(1)增加SQL審核機制,不合規(guī)范的SQL不允許上線;
(2)增加代碼審核機制;

場景三:查詢不走索引

現(xiàn)象

很常見的情況是,某些表最開始的數(shù)據(jù)量很小,后來由于產(chǎn)品功能重心的調(diào)整,變成了大表。之前做好的程序、SQL、表結(jié)構(gòu)卻沒有跟著調(diào)整。就出現(xiàn)了很多大表查詢,沒走索引,導(dǎo)致的慢查詢。而慢查詢堆積多了,整個數(shù)據(jù)庫就癱瘓了,于是就出現(xiàn)了“次要業(yè)務(wù)拖累主要業(yè)務(wù)”的現(xiàn)象。

建議

(1)根據(jù)查詢場景,設(shè)置合理的索引,組合索引優(yōu)先;
(2)當(dāng)組合索引和單字段索引同時存在時,建議刪掉單字段索引,避免優(yōu)化器做“無用功”;

場景四:線上數(shù)據(jù)和線下數(shù)據(jù)沒有隔離

現(xiàn)象

這里說的線上數(shù)據(jù),指的是直接面對廣大用戶的數(shù)據(jù);線下數(shù)據(jù),是面向公司內(nèi)部客服、運營的后臺系統(tǒng)用到的數(shù)據(jù)。后臺系統(tǒng)由于工作職責(zé)的不同,會有各種各樣的查詢需求,有的可能會很大、很復(fù)雜,比如導(dǎo)出一整個月、一整個季度的數(shù)據(jù)。會直接導(dǎo)致數(shù)據(jù)的壓力非常大,進而影響了整個數(shù)據(jù)庫實例,導(dǎo)致線上系統(tǒng)發(fā)生故障。

建議
  • 線上數(shù)據(jù)的特點是:

    1. 訪問量大;
    2. 每個用戶只查自己的數(shù)據(jù),可以命中索引;
    3. 查詢條件簡單;
    4. 返回條數(shù)少;
    5. 對響應(yīng)時間要求極高;
    6. 對數(shù)據(jù)的時效性要求高;
  • 線下數(shù)據(jù)的特點是:

    1. 訪問量小;
    2. 后臺同事會查詢整個平臺的數(shù)據(jù),不容易命中索引;
    3. 查詢條件復(fù)雜;
    4. 返回條數(shù)大;
    5. 對響應(yīng)時間要求不高;
    6. 對數(shù)據(jù)的時效性要求不是特別高;

綜上,兩類數(shù)據(jù)從各個方面都是完全不同的。要把線上數(shù)據(jù)和線下數(shù)據(jù)隔離開來。更新時,統(tǒng)一更新線上數(shù)據(jù);查詢時,線上查線上,線下查線下。線上數(shù)據(jù)通過DTS等實時數(shù)據(jù)同步的方式更新到線下。

場景五:過于依賴MYSQL,沒有考慮其他的存儲

現(xiàn)象

某些列表查詢類場景,可能涉及到10~20個查詢條件,而且檢索數(shù)據(jù)量一般也很大。此時再使用MYSQL就比較吃力了,索引幾乎無法覆蓋。

建議

除了關(guān)系型數(shù)據(jù)庫之外,我們有很多不同的數(shù)據(jù)存儲的選擇,比如:搜索引擎類、NOSQL類、時序類、緩存類,等等。應(yīng)當(dāng)根據(jù)不同的查詢場景,選擇最適合的數(shù)據(jù)存儲方式。企圖用MYSQL解決一切問題,是不明智的。

場景六:沒有站在數(shù)據(jù)庫的角度去思考

現(xiàn)象

比如,子查詢。開發(fā)站在人類的角度思考問題,就會出現(xiàn)形如:

SELECT * FROM table1 WHERE id IN ( SELECT id FROM table2 ); 

這種子查詢。而MYSQL在處理子查詢的時候,是拿外層的每一條數(shù)據(jù),去內(nèi)層掃描,結(jié)果就是掃描了table1的行數(shù) × table2的行數(shù)次。

建議

避免使用子查詢,改為通過索引做表關(guān)聯(lián)等方式;

場景七:直接在數(shù)據(jù)庫中做計算

現(xiàn)象

部分開發(fā)會在SQL中寫例如case when、group by + count/sum等的計算。MYSQL擅長的是,數(shù)據(jù)的查詢與存儲,并不擅長做計算——雖然它可以做。導(dǎo)致出現(xiàn)了很多慢SQL。MYSQL只對查詢做了優(yōu)化,并沒有對計算做優(yōu)化。

建議

(1)group by + count/sum可以考慮進行預(yù)計算;
(2)case when可以在業(yè)務(wù)端或者前端進行;
(3)要有效利用每個工具最擅長做的事。

場景八:在索引字段上用函數(shù)

現(xiàn)象

部分表在bigint類型的、存放時間戳的字段上做了索引,而查詢的條件是精確到天的。某些開發(fā)就會把SQL寫成:

WHERE from_unixtime(create_timestamp) >= '2018-01-01' AND from_unixtime(create_timestamp) < '2018-02-01' 

這樣。在索引字段上使用函數(shù),索引就起不到作用,掃描數(shù)據(jù)的時候依然是全表掃描,并對每一行數(shù)據(jù)的create_timestamp做from_unixtime運算。

建議

如:

WHERE from_unixtime(create_timestamp) >= '2018-01-01' AND from_unixtime(create_timestamp) < '2018-02-01' 

這種場景,可以改為:

WHERE create_timestamp >= unix_timestamp('2018-01-01')
AND create_timestamp < unix_timestamp('2018-02-01') 

這樣,只會計算一次,然后直接去匹配索引。避免了全表掃描。

場景九:沒有充分利用緩存

現(xiàn)象

部分對數(shù)據(jù)實時性要求不高的場景。會有相同條件的查詢頻繁執(zhí)行的情況,甚至于并發(fā)執(zhí)行多個相同查詢條件的查詢。這時候如果每次都查詢數(shù)據(jù)庫,勢必造成了資源的浪費。

建議

把這部分查詢結(jié)果,緩存到redis中。把大部分請求量引到redis去。

場景十:單表數(shù)據(jù)量過大

現(xiàn)象

由于對MYSQL依賴嚴(yán)重,導(dǎo)致很多更適合存在NOSQL數(shù)據(jù)庫的數(shù)據(jù),也被存到了MYSQL中,而且行數(shù)非常多。這樣的表,無論是查詢、還是更新、或是DDL操作,都需要停服之后、花大量時間去做。

建議

(1)單表不要超過1千萬行,大小不要超過5G;如果超過,可以考慮分庫分表;
(2)根據(jù)場景,考慮用其他數(shù)據(jù)存儲工具、或其他業(yè)務(wù)上的邏輯來解決大表的問題;

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI