mysql千萬級大表的優化

千萬級大表,這是一個很有技術含量的問題。一般碰到這種問題,我們下意識的會想對錶進行拆分或者分區,但是其實,要從多個維度去考慮這個事情。

問題分解

我們首先找到關鍵字:

千萬級
大表
優化

那麼也就對應了相應的知識點:

數據量
操作對象
動作和結果

數據量

千萬級是什麼概念呢?

假設我們的主鍵是bigint類型,佔據64位(8字節)空間,從btree進行索引的查找。需要遍歷幾次呢?

這裏我們首先需要了解一個東西,即操作系統的分頁。一般現在的操作系統頁大小爲4K,mysql的innodb的頁大小默認配置的爲16K。 而根據b+tree結構,每個節點保存的KEY的數量爲pagesize/(keysize+pointsize)(如果是B-TREE索引結構,則是pagesize/(keysize+datasize+pointsize))。一個節點可以存貯的數據量爲16*1024/(8+8)*8,最多可以存儲128個索引值。

假設我們的數據爲3000W(2的25次方爲33554432)可以得出,(log2^25)/log128 ≈ 25/7 ≈ 3.57。因此一個千萬量級,且存儲引擎是MyISAM或者InnoDB的表,其索引樹的高度在3~5之間。可以看出,高度並不是特別的大。

當然,數據量我們也要通過業務屬性來進行合理優化。

  1. 流水、日誌型記錄。

    通常是一些數據流水,日誌記錄的業務,裏面的數據隨着時間的增長會逐步增多,超過千萬門檻是很容易的一件事情。

  2. 一個相對穩定的數據。

    比如一個穩定的用戶表,業務穩定期不會得到大規模增長。

  3. 過分的冗餘了數據。

操作對象,數據表

數據操作的過程就好比數據庫中存在着多條管道,這些管道中都流淌着要處理的數據,這些數據的用處和歸屬是不一樣的。

根據業務區分的話,一般分爲3中數據類型。

  1. 流水型數據
  2. 狀態型數據
  3. 配置型數據
流水型數據

流水型數據,一般也稱之爲日誌型數據,並沒有實際的強業務關聯,每次業務都一定會產生,因此,體量比較大,並且不依賴前面和後面的數據,數據一般按時間線性增長。

狀態型數據

狀態型數據就是有狀態,這個狀態怎麼理解呢?可以引申爲事務,強關聯。當A成功B也必須成功這種。

配置型數據

配置型數據,一般數據量都很小,這裏就不用參與討論了。

通常,對業務的數據量分析,應該具有一個辯證的思維去看待,進行合理的優化。

優化,動作和結果

優化,我們可以從哪些方面開始呢?

  1. 規範設計,這個可以參照(阿里巴巴mysql規範),記住,是參照,不是抄。
  2. 業務層優化
  3. 架構層優化
  4. 數據庫優化
  5. 管理優化

其實我們通常所說的分庫分表等方案只是其中的一小部分,如果展開之後就比較豐富了。

作爲一個業務開發者角度,我們並不多贅述DBA應該盡的職責,我們多從業務角度去考慮怎麼優化。

規範設計

規範的本質不是解決問題,而是杜絕一些潛在的問題實現。

舉個栗子,索引的建立,數據庫字段的長度。這些都應該有規範可依循。

配置規範

innodb
項目內部字符集統一,utf8mb4
默認事務級別調整,RR=》RC,提高併發性能(根據業務來)
預估數據表數據量,提前進行合理的建表拆分。mysql建議在2000W以內

建表規範

外鍵不適合innodb
浮點數建議用decimal而非float和double
整型定義不去進行自定義寬度
enum使用tiny替代
儘量少用長文本、長二進制類型,如果業務要求使用,儘量拆分
字段not null

命名規範

小駝峯
長度建議小於12
儘量要能見名知意

索引規範

命名: idx_col1_col2......,uniq_col1_col2......
聯合索引字段不超過5個
單表索引不超過5個
主鍵索引一般選用自增或者雪花算法實現,保證整體有序
不建議使用%前綴模糊查詢,例如LIKE “%weibo”,無法用到索引,會導致全表掃描
UPDATE、DELETE語句需要根據WHERE條件添加索引。
避免在索引字段上使用函數,否則會導致查詢時索引失效。

開發規範(主流業務瓶頸基本出在mysql)

避免使用mysql自帶功能:存儲過程、觸發器、自定義函數
減少排序
統計儘量使用緩存,進行離線計算
字段變更需標註原有意義
使用預處理防止sql注入
sql in長度限制
禁止select *
批量insert長度的限制
業務層優化

此處常見的就是對數據表的業務類型進行分析。讀多寫少,讀少寫多

業務拆分:

  1. 將混合業務拆分爲獨立業務
  2. 講狀態和日誌型數據分離

表水平拆分:

  1. 按照日期拆分(全局日誌類型)
  2. 按照取模拆分 (恆定關聯的數據類型)
  3. 分區,mysql我個人不建議

另外,對高頻讀數據可以進行緩存優化

高頻寫的業務一般進行解耦,異步寫入,防止阻塞,並且還可以通過降低寫入頻率(比如合併寫入)

架構層優化

這一塊其實通常是DBA職責,如果我們已經晉級高T的話,通常會需要和DBA協商。

  1. 系統擴展,使用中間件
  2. 讀寫分離
  3. 負載均衡
  4. 離線業務剝離
  5. nosql異構
數據庫優化

事務優化,減小事務影響的數據和表

sql優化,通常出現slow sql進行explain分析,儘量減少關聯和查詢條件

索引優化,儘量命中索引,儘量減少範圍查詢,儘量在大表中杜絕全表掃描。

總結:

千萬級大表的優化是根據業務場景,以成本爲代價進行優化的,絕對不是孤立的一個層面的優化。一定要結合業務進行,否則,優化就是吹牛逼。

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