數據庫大表調優策略總結

數據庫大表優化是我們開發中面臨的最直觀的問題,我將其分爲兩個層次,一個層次是數據庫層次的,另一個層次是服務優化層次。

簡介

數據庫層次的調優最常見的策略是分表(垂直分表),其次是sql優化,索引優化,而後是緩存。再之後是主從複製,讀寫分離,分庫分表分區。不要以爲這就完了,其實對一個大型服務來說,以上措施基本是常規必做,但是註定收效甚微。上面的措施對服務能力的提升非常有限。我們拿最終措施分庫分表分區來說,大部分適合我們將其劃分爲服務高可用範疇,而不是數據庫調優範疇,但是分庫分表分區首先與數據庫集羣的協調能力,我們不可能無限分庫分表。分區同時受限於數據庫支持的文件大小,也不可能無限制分區。另外一個問題是成本問題啊,分庫分表分區帶來的是數據庫服務某一個方面的性能提升,但是對於服務器來說,服務器的整體性能並沒有發揮出來,作爲企業必須考慮成本問題,比可能大量的浪費機器資源在這上面。但是當這些都達到服務極限的適合我們該怎麼進行數據庫調優呢?

服務層次的調優比較常見的是全文索引(lunace),數據熱點,機器學習。這部分我個人認爲核心思想還是基於數據倉庫數據集市的理念,通過對數據進行預處理將數據拆分爲一個個小的數據集合,然後通過機器學習,實時計算快速匹配到對應的服務。但是不管是那種情況,對用戶而言最終面對的數據集合都是非常有限的。在我們之前的文章中提到newsql其實大體就是這個理念,newsql對數據的使用不在侷限於數據是否一定要來自數據庫,他可以是文件,也可以是內存,也可以是用戶緩存。擺脫了數據庫本身對數據的約束他也就有了快的資本。newsql對數據的使用也不在侷限與具體的數據結構,它可以是數據庫記錄,也可以是haspmap,list等常見的數據結構,擺脫了數據庫數據結構的現在,算法上就可以選擇更大的空間,我們知道數據庫通過B+Tree存儲數據,但是平衡樹,跳躍表,雙數組等等效率都比B+Tree有過之而無不及。但是這部分內容說實在的實現起來非常的麻煩,首先技術棧這一關很多企業都會避而遠之了。(其實有很多變通的方法的,只是對於閹割版的,或許會讓你性質缺缺,而且有些東西一點就透,自己好好省核一下自己的代碼很容易就會發現,很多東西我們已經不知不覺的在用了)。

如果看到這裏你還在看,那麼我也不能偷懶了,下面整理了一些我們常見但不常用的數據庫層次的優化策略。數據庫層次的優化主要有兩個點,一個是使用索引的使用,另一個問題是減少單表數據量,第三個是業務分流,提高IO效率。

優化sql


優化sql主要是爲了避免全表掃描和提高數據過濾量,常見措施包括:

  1. 儘量避免Like的參數以通配符開頭,否則數據庫引擎會放棄使用索引而進行全表掃描。
  2. 不以通配符開頭的sql語句,例如:select * from table1 where code like '%jone%'
  3. 避免where條件不符合最左前綴原則,最左前綴決定使用的索引,mysql會一直向右匹配直到遇到範圍查詢(>、<、between、like)就停止匹配,也就是說範圍查詢之前的條件是我們查詢中使用的索引。
  4. 儘量避免使用!= 或 <>操作符
  5. 避免在 where 子句中對字段進行表達式操作
  6. 避免在where子句中對字段進行null值判斷
  7. 避免在where子句中使用or來連接條件
  8. 避免在order by子句中使用表達式,合理使用過濾條件減少數據量
  9. 提高GROUP BY 語句的效率,合理使用過濾條件減少數據量
  10. 用 exists 代替 in
  11. 儘量使用DISTINCT的代替GROUP BY
  12. 儘量用UNION ALL 代替UNION,UNION ALL不執行SELECT DISTINCT函數
  13. 不要在 where 子句中的“=”左邊進行函數、算術運算或其他表達式運算
  14. 儘量使用表變量來代替臨時表
  15. 避免頻繁創建和刪除臨時表
  16. 儘量使用數字型字段
  17. 使用變長 varchar/nvarchar 代替 定長char/nchar
  18. 如果使用到了臨時表,在存儲過程的最後務必將所有的臨時表顯式刪除,先 truncate table ,然後 drop table ,這樣可以避免系統表的較長時間鎖定
  19. 儘量避免使用遊標
  20. 儘量避免大事務操作,提高系統併發能力
  21. 儘量避免向客戶端返回大數據量

優化索引

  1. 對出現在where子句中的字段加索引
  2. 大量非重複值的列,避免使用索引
  3. 索引字段避免出現null
  4. 頻繁更改的列,避免使用索引,會提高索引維護成本,降低服務器效率

以上是sql和索引的常見優化策略,常見但是很垃圾的策略,你能否想象當你費盡心思完成這些之後,你的架構師告訴你擴容服務器一次提高一倍的性能;數據表拆分吧一次性將數據降低好幾個數量級的適合,你會是一種什麼樣的心態。sql優化、索引優化可以成爲研發人員的一種素養,自然而然體現出來就好,如果真的要爲一個sql去挖空心思,那絕對會得不償失。下面的部門主要整理了一些常見的數據庫層數的優化,其實這部分與其說提升sql效率,我覺得更多的應該歸爲服務高可用一類。

主從複製、主主複製

數據熱備,服務高可用,提高單個機器的I/O性能,性能優化這塊,主從複製和主主複製主要是提供IO效率。


讀寫分離


讀寫分離通常伴隨主從複製,除了具有主從複製的特性外,讀寫分離將極大程度的緩解X鎖和S鎖爭用和數據查詢分離從而提高單機效率。

分區、垂直分表、水平分表

表分區是將數據存在不同的持久化設備上,其實就是將一張大數據量表中的數據按照不同的分區策略分配到不同的系統分區、硬盤或是不同的服務器設備上,實現數據的均衡分配,這樣做的好處是均衡大數據量數據到不同的存儲介子中,這樣每個分區均攤了一部分數據,然後可以定位到指定的分區中,對數據表進行需求操作。在MySql中支持四種表分區的方式,分別爲HASH、RANGE、LIST及KEY,HASH分區主要用來確保數據在預先確定數目的分區中平均分佈,而在RANGE和LIST分區中,必須明確指定一個給定的列值或列值集合應該保存在哪個分區中,而在HASH分區中,MySQL自動完成這些工作。

  • 分表是將數據存放在不同的結構相同的表中,其實就是將一張大數據量的表分成多個小表實現數據均衡。
  • 垂直分表是將一個表的數據拆分爲多個表,每個表保留一部分的數據集合,確保但表中數據更集中有效精簡,以減少空間浪費,提高單位空間數據存儲能力。
  • 水平分表是將一個表的數據根據不同的維度進行拆分,每個表保存某一維度的所以數據,確保每個表中的數據量比較少。
  • 分區和分表策略同樣受限於數據庫支持的文件大小,如果分區分表後數據量依然比較大則要考慮進一步的拆分。

總結:總結:以上都是一些看起來非常有效,實際上基本是雞肋的策略。特別是sql調優和索引優化這部分。爲什麼這麼說呢,軟件設計不僅僅是技術棧的使用,還有很重要的一部分是邏輯的優化。比如在一個大表裏面爲了避免數據重複,需要重複多次的去查表驗證或者查緩存。此時按理說sql優化,索引優化,所有的數據庫優化都很重要。但是問題是我們是不是有必要一定去去重,或者說是不是一定要在這個業務環節去重。如果這個環節去重是飛必要的,那麼你想想你做那麼多的優化,意義何在。在使用技術棧的適合我們常常會忽略邏輯優化這個更重要的問題。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章