什么情況需要考慮 mysql 分表
最近看到公司的其中一個數(shù)據(jù)庫用戶表每個月都要幾百萬的新用戶數(shù)據(jù)增加,目前單表已經(jīng)是兩千多萬了。所以找了 DBA 討論,發(fā)現(xiàn)以前學(xué)的知識,以及網(wǎng)上的一些資料其實說的并不是很正確,比如 mysql 單表不建議超過一千萬,我司 DBA 數(shù)據(jù)規(guī)范建議是單表最多不超過五千萬。DBA 認為單看數(shù)據(jù)表的行數(shù)來決定分不分表是不正確。結(jié)合自己的知識和 DBA 的建議,記錄一下需要分表的場景:
1. 表字段多,部分字段不經(jīng)常用,使用 show index from tablename 查看索引狀態(tài)
2. 表數(shù)據(jù)占物理空間大
3. 數(shù)據(jù)庫服務(wù)器性能問題,使用 show processlist 查看當(dāng)前連接狀態(tài),是否有慢 sql
4. 業(yè)務(wù)查詢較多,查詢慢,使用 explain 查詢 sql 是否使用索引
5. 業(yè)務(wù)受到影響,不滿足日常需求
分表方式有水平分表,垂直分表。常用的水平分表都是 RANGE 、一致性 HASH 算法 、取模幾種方式。分表之后,業(yè)務(wù)代碼、架構(gòu)也需要調(diào)整,比如引入中間件,否則分頁,排序,事務(wù)都無法處理。
分享一下我 2020 年開發(fā)的一個支付系統(tǒng) MySQL 按月水平分表的例子,當(dāng)時每天有 10 萬筆訂單,單表已經(jīng) 3000 多萬的數(shù)據(jù),常用查詢字段訂單號、訂單狀態(tài)、創(chuàng)建時間、商戶id、字段已經(jīng)有添加索引了,查詢性能比較差,一個查詢要2-3秒。
以下是技術(shù)升級改造處理過程:
1. 原有表名為 orders,批量創(chuàng)建一年的分表,按訂單創(chuàng)建時間的月份創(chuàng)建,表名為 orders_202001 orders_202002 以此類推,訂單流水表也是類似。
2. 創(chuàng)建訂單時按獲取創(chuàng)建時間加表名,得到分表名稱寫入數(shù)據(jù),創(chuàng)建時間也作為訂單號的前綴,根據(jù)訂單號查詢時也能獲取到分表名稱
3. 將管理后臺涉及查詢的接口繼續(xù)改造,添加限制條件,最多只能查詢 2 個月時間內(nèi)的訂單,超出的分多次查詢,調(diào)研了金融類項目都有查詢時間限制,可能也是做了水平分表,避免分表之后需要查詢所有數(shù)據(jù)表,查詢性能比沒有分表更差,查詢訂單數(shù)據(jù)時,我們可以使用 UNION ALL 操作符將不同分表的數(shù)據(jù)合并在一起。
分表之后的業(yè)務(wù)價值有兩點:
1. 查詢性能提升、用戶體驗更佳。
2. 節(jié)省服務(wù)器成本,如果沒有分表,數(shù)據(jù)庫服務(wù)器升級配置也可以滿足,但是成本更高了。