千萬級大表,這是一個很有技術含量的問題。一般碰到這種問題,我們下意識的會想對錶進行拆分或者分區,但是其實,要從多個維度去考慮這個事情。
問題分解
我們首先找到關鍵字:
千萬級
大表
優化
那麼也就對應了相應的知識點:
數據量
操作對象
動作和結果
數據量
千萬級是什麼概念呢?
假設我們的主鍵是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之間。可以看出,高度並不是特別的大。
當然,數據量我們也要通過業務屬性來進行合理優化。
-
流水、日誌型記錄。
通常是一些數據流水,日誌記錄的業務,裏面的數據隨着時間的增長會逐步增多,超過千萬門檻是很容易的一件事情。
-
一個相對穩定的數據。
比如一個穩定的用戶表,業務穩定期不會得到大規模增長。
-
過分的冗餘了數據。
操作對象,數據表
數據操作的過程就好比數據庫中存在着多條管道,這些管道中都流淌着要處理的數據,這些數據的用處和歸屬是不一樣的。
根據業務區分的話,一般分爲3中數據類型。
- 流水型數據
- 狀態型數據
- 配置型數據
流水型數據
流水型數據,一般也稱之爲日誌型數據,並沒有實際的強業務關聯,每次業務都一定會產生,因此,體量比較大,並且不依賴前面和後面的數據,數據一般按時間線性增長。
狀態型數據
狀態型數據就是有狀態,這個狀態怎麼理解呢?可以引申爲事務,強關聯。當A成功B也必須成功這種。
配置型數據
配置型數據,一般數據量都很小,這裏就不用參與討論了。
通常,對業務的數據量分析,應該具有一個辯證的思維去看待,進行合理的優化。
優化,動作和結果
優化,我們可以從哪些方面開始呢?
- 規範設計,這個可以參照(阿里巴巴mysql規範),記住,是參照,不是抄。
- 業務層優化
- 架構層優化
- 數據庫優化
- 管理優化
其實我們通常所說的分庫分表等方案只是其中的一小部分,如果展開之後就比較豐富了。
作爲一個業務開發者角度,我們並不多贅述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長度的限制
業務層優化
此處常見的就是對數據表的業務類型進行分析。讀多寫少,讀少寫多
業務拆分:
- 將混合業務拆分爲獨立業務
- 講狀態和日誌型數據分離
表水平拆分:
- 按照日期拆分(全局日誌類型)
- 按照取模拆分 (恆定關聯的數據類型)
- 分區,mysql我個人不建議
另外,對高頻讀數據可以進行緩存優化
高頻寫的業務一般進行解耦,異步寫入,防止阻塞,並且還可以通過降低寫入頻率(比如合併寫入)
架構層優化
這一塊其實通常是DBA職責,如果我們已經晉級高T的話,通常會需要和DBA協商。
- 系統擴展,使用中間件
- 讀寫分離
- 負載均衡
- 離線業務剝離
- nosql異構
數據庫優化
事務優化,減小事務影響的數據和表
sql優化,通常出現slow sql進行explain分析,儘量減少關聯和查詢條件
索引優化,儘量命中索引,儘量減少範圍查詢,儘量在大表中杜絕全表掃描。
總結:
千萬級大表的優化是根據業務場景,以成本爲代價進行優化的,絕對不是孤立的一個層面的優化。一定要結合業務進行,否則,優化就是吹牛逼。