關於SQL優化這些你瞭解嗎?

關於SQL優化這些你瞭解嗎?

背景

  在當今這個互聯網的時代無非要解決兩大難題,其一是信息安全,其二就是數據的存儲。而信息安全則是在數據存儲的基礎之上。一個公司從剛開始成立到發展成一個有上百人甚至上千人團隊的時候,公司的業務量是呈上升趨勢,客戶及用戶也會愈來愈多;以前設計的表結構可能會顯得不合理,表與表之間的聯繫沒有一個穩定的業務功能劃分,從而表現出來的是相關表的備用字段愈來愈不夠用甚至新加字段,最壞的狀況就是不一樣業務表之間會有數據冗雜。從而暴露出一些設計的問題,這也就是SQL優化點之一:數據庫表結構設計的合理性。近年來大數據愈來愈火,而大數據也是爲了解決數據的存儲的手段之一,其目的是從海量的數據中收集到有價值的信息而後存儲到數據庫中,由於數據量大傳統的數據庫沒法儲存那麼多的信息因此須要分析有價值的信息後再作決定是否持久化。html

優化點數據庫

  • 前提必備知識

  學會是用explain關鍵詞查看SQL語句性能,explain好像是從MYSQL5.6.3開始支持 select、update、delete語句分析,以前只支持select語句。如今咱們廣泛都是用5.7,因此的話不須要太擔憂。這裏的話不詳細講如何解讀explain輸出的性能信息。請參看博客文檔:《MySQL優化之Explain命令解讀》緩存

  • 優化之一 - 從數據庫設計方面考慮
  1. 表與表之間的業務聯繫要明確:表之間實際上是有業務聯繫的,好比:class(primary key:class_id,全部班級信息表)、student(primary key:student_num,全部學生信息表)、student_class(primary key:stu_class_id,全部學生所在班級信息表)着三張表,若是如今須要一張老師對應哪一個班級的班主任的信息表;那麼此時正確的方法是:新建 teacher、teacher_class表,而不是直接把老師的信息插入到student表中而後用一個字段來標識是老師仍是學生。可能你看到這個你會想 「我確定會按正確的那種方式啊」,可是這只是舉一個例子,其實在實際項目開發過程當中表與表結構每每不會那麼單一,這個時候你就會犯錯誤而用字段標識。可是也不能說是不能用字段標識,這個要看字段標識的兩種信息對應的業務是否有交叉點來取捨。
  2. 表字段儘可能使用數值型:由於數值型字段在MySQL底層應用的時候相比string類型的話性能更好;具體爲何性能更好就須要瞭解MySQL底層機制了,反正記住這點就好。
  3. 屬性儘可能使用定長:以減小佔用儲存空間;若是你定義了一個 order_id varchar(32) ,當在存儲的時候有一條記錄的order_id=20180910242360,此時order_id實際佔用了14個字節可是這個字段的屬性長度是32,因此還有18個字節長度是無用的但卻佔用着內存空間。
  4. 創建合理的索引:索引就是用某種數據結構來查找對應的信息,從而減低時間複雜度提升查找效率。創建索引的前提也要明確,綜合考慮再打算是否須要創建索引,畢竟索引是須要佔用存儲空間的,有時候犧牲的空間卻換不回時間。
     
  • 優化之二 - 從SQL語句優化方面考慮

  1. 儘可能將要輸出的字段寫出來;不要使用 select * from where xxxxx ;這種形式的語句。我在這測試時是使用*代替,可是記住在生產環境上儘可能將字段替代*。安全

  2. 合理使用連表查詢;不只是表的鏈接須要較大的內存消耗另一方面若是表設計的不是很合理也會致使索引無效從而形成極壞的結果。性能優化

  3. 查詢的時候要注意是否走索引:假如你在name列創建了一個 name_index索引,查詢你使用 name Like'%xxxx' 或者 name Like'%xxxx%' 這種模糊查詢,那麼此時可能就不會走索引;你應該這樣  name Like'xxxx%' 。如下就是實際的一個例子:  數據結構

  創建索引:架構

-- 爲cust_third_acct 創建一個普通索引
alter table
cust_info
add index cust_third_acct_index(cust_third_acct);

 

  a:經過SQL查詢信息: select * from sp_tunnel_user where cust_third_acct like'0200%';   如下就是知足查詢條件的部分信息併發


  b:分析Like'%xxxx%'的查詢性能: select * from sp_tunnel_user where cust_third_acct like'%0200%';  經過Explain性能分析命令能夠知道:在這種查詢條件下並無執行索引,type=all代表該語句執行的時候進行的是全表掃描;雖然咱們在 cust_third_acct  這個字段創建了索引,可是 possible_keys=null 則說明了 用 like'%0200%' 這種形式的條件是必定沒法使用到  cust_third_acct_index  這個索引。(其餘字段的解析請參照《MySQL優化之Explain命令解讀》這篇文章,這裏不作過多的分析)。數據庫設計

    

  c:分析Like'xxxx%'的查詢性能: select * from sp_tunnel_user where cust_third_acct like'0200%';  與b查詢語句相比這個查詢的  possible_keys=cust_third_acct_index  ,這說明這個語句可能會用到 cust_third_acct_index 這個索引,可是key=null代表在實際的執行過程當中並無用到  cust_third_acct_index  索引;剛纔咱們也說了這種條件查詢只是可能會走索引可是不必定發生,這個跟MySQL的存儲引擎相關,可是咱們使用的時候儘可能以這種方式去查詢。分佈式

  

  4. 使用索引遵循最佳左前綴特性,創建聯合索引的時候將經常使用的屬性放在左邊。好比:咱們需在在一張表的 cust_id 和 cust_tp 創建一個聯合索引 cust_id_type,設定cust_id(不是惟一) 是比較經常使用的那麼咱們就將cust_id放在左邊。

  創建聯合索引:

-- 爲cust_id與cust_tp創建一個聯合索引
alter table
cust_info
add index  cust_id_type(cust_id,cust_tp);

 

  5.使用符合索引的時候須要注意:使用聯合索引須要從左往右不間斷,索引纔會生效,也就是說聯合索引使用的時候必需要連續但不要求所有使用。如:以上4咱們創建了一個  cust_id_type  索引,當咱們在使用的時候若是where條件中只使用了 cust_id,那麼也會走索引;若是where條件中只使用了 cust_tp,那麼這條語句不會走索引,如下就是一個實例:

  a:select * from sp_tunnel_user where cust_id='8888888888' and cust_tp='04';  當查詢條件用到cust_id與cust_tp兩個字段而且cust_id在前面的時候,就會用到聯合索引;經過 key=cust_id_type能夠看到實際執行過程當中是用到索引了的。

 

  b:select * from sp_tunnel_user where cust_id='8888888888' ;  當查詢條件只用到cust_id一個字段時,也用到了聯合索引;經過 key=cust_id_type能夠看到實際執行過程當中是用到索引了的,這就是左前綴原則。

 

  c:select * from sp_tunnel_user where cust_tp='04' ;  當查詢條件只用到cust_tp一個字段時,但卻沒有用到索引;經過 key=null 能夠看到實際執行過程並無用到索引,這也是左前綴原則。

 

  • 優化之三 - 讀寫分離與分庫分表

  當數據量達到必定的數量以後,限制數據庫存儲性能的就再也不是數據庫層面的優化就可以解決的;這個時候每每採用的是讀寫分離與分庫分表同時也會結合緩存一塊兒使用,而這個時候數據庫層面的優化只是基礎。讀寫分離適用於較小一些的數據量;分表適用於中等數據量;而分庫與分表通常是結合着用,這就適用於大數據量的存儲了,這也是如今大型互聯網公司解決數據存儲的方法之一。至於怎麼讀寫分離、怎麼分表、怎麼分庫,這裏不作過多的闡述後續文章會有相關知識分享。

順便在此給你們推薦一個Java架構方面的交流學習羣:698581634,裏面會分享一些資深架構師錄製的視頻錄像:有Spring,MyBatis,Netty源碼分析,高併發、高性能、分佈式、微服務架構的原理,JVM性能優化這些成爲架構師必備的知識體系,主要針對Java開發人員提高本身,突破瓶頸,相信你來學習,會有提高和收穫。在這個羣裏會有你須要的內容  朋友們請抓緊時間加入進來吧。

相關文章
相關標籤/搜索