會優化,你真的會優化嗎?其實你可能真的缺少一份理解【數據庫篇】


  其實,在寫這篇博客之前,我也是感覺自己會點優化,至少知道不要使用“*”號啊,給經常查詢的列創建索引啊什么的,其實都不是大家想的那樣簡單的,其實它們背后存在很多的東西,值得我們去理解和學習。

  和大家分享討論一個問題吧,子查詢連接查詢哪一個查詢速度快?最重要的目的是能幫助大家在以后的開發路上不要再犯我這種的錯誤,看到就是賺到,哈哈。

我的答案是連接查詢。因為這是我在前幾天的實踐項目中親身體會到的,感觸頗深,在給我們公司的網站首頁執行了一條統計SQL語句,當時我是用子查詢寫的sql語句,第一次執行了21.783sec,第二次執行了5.178sec,當時感覺很別扭,一個網站的首頁加載要經過3-4秒鍾才能刷出統計數據,太離譜了,於是我就嘗試用連接查詢進行改造一下,果然,查詢速度嗖一下上去了,當時感覺有種征服了什么東西一樣,真的,超有成就感,以前確實是寫代碼,沒在這方面過多留意過,這次鑽了一次確實挺好。

  直接上圖吧,給大家展示一下子查詢和連接查詢的執行時間,(但是,一條sql語句的性能不能光靠查詢時間來衡量,之前在一篇博文里看到的,蠻有感覺的)

  一、子查詢統計

執行了5.198sec

  二、連接查詢統計

執行了0.010sec。

  (為什么連接查詢比子查詢塊,這個問題我一直在總結,比較它們的查詢原理是如何掃描表結構的,一致還沒能總結出一個舒服的答案,等后期總結好了分享,更希望高手指點,希望高手留言相助,正在努力理解...)

  好了,跟大家分享一點小東西之后,我們就切入正題,來談談簡單優化及它們是如何來提升性能的。

  1、MySQL的查詢過程:當我們通過MySQL的客戶端發送一條SQL語句時,MySQL服務器到底做了哪些動作,經歷了哪些過程,我還是借圖說明吧

  簡單給大家說明一下吧。

  MySQL數據庫也是客戶端/服務端通信協議的模式,在任意時刻,無非就是要么客戶端向服務端發送請求,要么服務端向客戶端響應查詢結果,這兩個動作不能同時發生。一旦一端開始發送消息,另一端要接收完整個消息才能響應它,所以我們無法將一個請求消息切成小塊獨立發送,也沒有辦法進行流量控制。

當客戶端向服務端發送sql語句時,首先客戶端會把查詢語句做成一個單獨的數據包發送給服務端,這時如果查詢語句很長則需要設置參數,如果實在太大,服務端可能會拒絕接受更多數據並拋出異常。

同理,與之相反的是服務端從存儲引擎中拿到數據后響應給客戶端,這時服務端響應的數據可能會很多,無法將這些數據做成一個數據包,可能會做成多個數據包。但是當服務器響應客戶端請求時,客戶端必須完整的接收整個返回結果,而不能簡單的只取前面幾條結果,然后讓服務器停止發送。因而在實際開發中,盡量保持查詢簡單且只返回必需的數據,減小通信間數據包的大小和數量是一個非常好的習慣,這也是查詢中盡量避免使用SELECT *以及加上LIMIT限制的原因之一。

  2、查詢時盡量使用limit做限制查詢,原因上面已經分析,服務端可能會響應大量的數據包給客戶端,我們通常只拿到前幾條數據,后面的數據如果需要,則可以使用分頁查詢,邊用邊查。

  3、還有一個誤區就是,當我們在設計表結構時,盡量將字段的數據類型設置到最小,夠用就行,別瞻前顧后,就拿int類型來說吧,我們習慣將給int類型的字段設置長度,其實吧,你設置不設置都沒什么卵用,int類型是采用16位存儲空間,那么它的存儲范圍就已經確定,所以int(1)和int(20)對於存儲和計算是相同的,大家改改吧,我也是剛學到的。

  4、我們在查詢數據庫,可能會用多個范圍條件來作限制,比如查詢某一時間段內入職的某一年齡段的員工,此時需要接納的一點是,MySQL無法同時使用倆個字段的索引,它只會選擇一種的一個字段的索引來做查詢。

  5、建議大家經常把表中一些不常用的索引刪掉,定期刪除一些長時間未使用過的索引是一個非常好的習慣。(在這兒給大家囑咐一下,不要認為索引就是查詢最好的工具,如果有時候查詢非常小的表時,建議不要建立索引,直接全表掃描效果會更好)。

 

優化的學習旅程才剛開始,后期會給大家帶來更多的經驗,非常希望大家能夠看到並給出建議。

參考博文:

  http://www.cnblogs.com/zishengY/p/6892345.html,http://blog.csdn.net/luckarecs/article/details/7165472

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM