DBA推薦的7法寶提高SQL查詢性能
SQL查詢數(shù)據(jù)庫(kù)時(shí),適當(dāng)遵循一些原則可以讓工作變得更加輕松,本文就列舉7個(gè)可以靈活運(yùn)用的原則,它們可以幫助你提高SQL查詢速度,當(dāng)然這些技巧你可以咨詢DBA獲得更多的信息。
1、用case代替update
要更新一條記錄,我們立即會(huì)想到update,這個(gè)問(wèn)題非常常見(jiàn),許多開(kāi)發(fā)人員經(jīng)常忽視這個(gè)原則,因?yàn)槭褂胾pdate看起來(lái)非常自然,非常合乎邏輯。
假設(shè)你從Customer表中提取記錄,你想將超過(guò)10萬(wàn)美元的訂單標(biāo)記為“Preferred”,因此你會(huì)想到使用一條update語(yǔ)句將CustomerRank列更新為“Preferred”,問(wèn)題是update語(yǔ)句是有日志的,這就意味著每條記錄它會(huì)寫(xiě)兩次,解決這個(gè)問(wèn)題的辦法就是在SQL查詢中內(nèi)嵌case語(yǔ)句,在向表寫(xiě)入“Preferred”標(biāo)志前,它會(huì)用訂單金額條件對(duì)每一行進(jìn)行檢查,滿足條件的才會(huì)更新,性能的提升是驚人的。
2、不要盲目地重用代碼
這個(gè)問(wèn)題也非常常見(jiàn),在工作中直接用別人寫(xiě)好的代碼是一件痛快的事情,你知道這些代碼可以查詢出你需要的數(shù)據(jù),但問(wèn)題是往往有些數(shù)據(jù)不是你需要的,但我們常常不愿意做一下修改,因此返回的數(shù)據(jù)集往往是一個(gè)超集,很可能多用一個(gè)外連接或是一個(gè)where子句就可以解決問(wèn)題,因此在復(fù)用代碼時(shí)***檢查一下,如有必要略做適應(yīng)性修改。
3、只提取你需要的列
這個(gè)問(wèn)題和2有點(diǎn)類似,但這次是指定具體的列。也許我們?cè)谑褂胹elect * 時(shí)感覺(jué)很暢快,多省事呀!如果要將每個(gè)列名都寫(xiě)出來(lái),太麻煩了,這是很多人的想法,但這種想法是錯(cuò)誤的,因?yàn)檫@樣做會(huì)取出多余的數(shù)據(jù)列,我無(wú)數(shù)次看到犯這種錯(cuò)誤的代碼,曾經(jīng)有一位開(kāi)發(fā)人員對(duì)一張有120列,上百萬(wàn)行數(shù)據(jù)的表使用select * 查詢,但他只會(huì)用到其中的三五列,這是對(duì)資源的極大浪費(fèi),我們建議拒絕書(shū)寫(xiě)select * ,你要什么就查詢什么,多余的返回結(jié)果對(duì)你沒(méi)用,雖然不影響你要實(shí)現(xiàn)的功能,但對(duì)數(shù)據(jù)庫(kù)性能卻有極大的影響。
4、盡可能只查詢一次大表
這也是我看到很多人犯的錯(cuò)誤,例如,某存儲(chǔ)過(guò)程從一張上百萬(wàn)條記錄的大表中取數(shù)據(jù),開(kāi)發(fā)人員想提取居住在加利福利亞且收入高于4萬(wàn)美元的客戶信息,因此它先將居住在加利福利亞的客戶取出放在一張臨時(shí)表中,然后再查詢收入高于4萬(wàn)美元的客戶,將查詢結(jié)果放入另一張臨時(shí)表中,***,他連接這兩張臨時(shí)表查詢出最終的結(jié)果。
可能有人認(rèn)為我是在開(kāi)玩笑吧?但事實(shí)是確實(shí)有人這么做,這應(yīng)該在一個(gè)查詢中就能完成,卻查詢了兩次大表。
有種稍微不同的情況是,當(dāng)一個(gè)過(guò)程中的多個(gè)步驟需要大表的子集時(shí),每一步可能都必須查詢一次大表。避免多次查詢的辦法是持久化***次查詢的子集,然后將后面的步驟指向該持久化子集。
5、使用臨時(shí)表
這個(gè)問(wèn)題解決起來(lái)可能稍微有點(diǎn)麻煩,但其效果比較明顯,其實(shí)在很多時(shí)候你都可以使用臨時(shí)表,通過(guò)臨時(shí)表可以有效地減少對(duì)大表的操作,如果你必須連接一個(gè)表到大表,并且在大表上有條件,這時(shí)就可以將大表中需要的數(shù)據(jù)輸出到臨時(shí)表中,然后再用該臨時(shí)表進(jìn)行連接,這樣查詢速度會(huì)有明顯改進(jìn)。如果你的存儲(chǔ)過(guò)程中有多個(gè)查詢需要需要連接到相同的表時(shí),也可以使用臨時(shí)表。
6、預(yù)存數(shù)據(jù)
這一條是我最喜歡的,因?yàn)樗且豁?xiàng)很老的技術(shù),常常被人們忽視,如果你有一個(gè)報(bào)表或存儲(chǔ)過(guò)程需要連接大表,提前提取大表中的數(shù)據(jù),持久化存儲(chǔ)到另一張表中,報(bào)表就可以使用預(yù)存的數(shù)據(jù)集,從而提高整體執(zhí)行效率。
并不是所有時(shí)候你都有機(jī)會(huì)利用該技術(shù),但一旦能利用上,你會(huì)發(fā)現(xiàn)它是節(jié)省服務(wù)器資源很有效的辦法。
但遺憾的是,很多開(kāi)發(fā)人員都在盡力回避這種技術(shù),實(shí)際上只需要?jiǎng)?chuàng)建一個(gè)視圖就可以把問(wèn)題解決了,但這種方法的問(wèn)題是每個(gè)需要它的報(bào)表運(yùn)行時(shí)都會(huì)執(zhí)行一次,但對(duì)于同一個(gè)報(bào)表,假設(shè)10分鐘前運(yùn)行了一次,現(xiàn)在有人要再運(yùn)行該報(bào)表,那么對(duì)大表的連接操作就可以避免掉了。我建議對(duì)那些經(jīng)常被查詢的表使用該技術(shù)將數(shù)據(jù)預(yù)存起來(lái),可以節(jié)省大量的服務(wù)器資源。
7、分批刪除和更新
這也是一個(gè)容易被忽視的技巧,對(duì)一個(gè)大表做數(shù)據(jù)刪除或更新操作,如果操作不當(dāng)可能是一場(chǎng)噩夢(mèng),問(wèn)題是這兩種操作都是單一的事務(wù),如果你需要?dú)⑺浪鼈儯蛩鼈冊(cè)趫?zhí)行時(shí)系統(tǒng)遇到問(wèn)題,必須全部回滾整個(gè)事務(wù),這個(gè)時(shí)間可能非常長(zhǎng),這就是為什么我們?cè)趧h除數(shù)十萬(wàn)條記錄時(shí),如果試圖中途殺死進(jìn)程幾乎沒(méi)用的原因,這些操作也會(huì)影響到其它事務(wù),搞不好會(huì)造成死循環(huán),因此應(yīng)慎用。
解決這個(gè)問(wèn)題的辦法就是分批少量刪除或更新,首先,無(wú)論什么原因需要結(jié)束事務(wù),只需要回滾少量的行,此外,小批量提交數(shù)據(jù)寫(xiě)入磁盤(pán),對(duì)I/O的要求也更低,并發(fā)性可以大大提高。
另外要提醒的是,執(zhí)行刪除和更新操作應(yīng)盡量選擇非高峰時(shí)段。
總結(jié)
遵循這些方法總是能收到效果,但在實(shí)踐中,我們應(yīng)該根據(jù)實(shí)際情況,選用一種或幾種***方案,來(lái)提高我們執(zhí)行查詢的速度,從而節(jié)省查詢時(shí)間,提高查詢效率。
【編輯推薦】