記一次Mysql單表億級數(shù)據(jù)的拆分方案

在實際的應用場景中,當一個單表的數(shù)據(jù)量過億時寫入和查詢的壓力就會倍增,拆表在一定程度上是解決數(shù)據(jù)庫單表瓶頸的方案之一,
在本次要拆分的表中有以下特征:

  1. 單表已過2億
  2. 表數(shù)據(jù)量每天增量50萬左右
  3. 表結(jié)構(gòu)比較單一,用戶關(guān)注用戶行為表,用戶關(guān)注一個用戶會往表中寫入一條數(shù)據(jù)。
    表結(jié)構(gòu)如下:
tb_user_friends:
uid, fid, from, create_date, inverse_date(反向索引時間戳)
其中表索引:
PRIMARY KEY (`uid`,`fid`),
KEY `idx_uid` (`uid`,`inverse_date`),
KEY `idx_fid` (`fid`,`inverse_date`),

如何選擇拆分鍵

選擇拆分鍵的選擇往往由查詢決定,常見的查詢語句如下:

// 獲取用戶的關(guān)注列表
select fid from tb_user_friends where uid = xxx order by inverse_date limit 20; 
// 獲取用戶的粉絲列表
select uid from tb_user_friends where fid = xxx order by inverse_date limit 20;

這就保證了我們查詢用戶的粉絲或者關(guān)注都需要從單一的一個表中能夠獲取到,所以如果單一的按照uid進行拆分,會導致查詢粉絲需要從多張表中查詢,這是不能接受的,所以這里分別以uid,fid作為拆分鍵拆成兩個主表如下:

tb_user_followers_000:
uid, fid, from, create_date, inverse_date
tb_user_fans_000:
uid, fid, from, create_date, inverse_date
結(jié)構(gòu)和上面的表保持一致,但索引如下:
PRIMARY KEY (`uid`,`fid`),
KEY `idx_uid` (`uid`,`inverse_date`),
這樣查詢變成了:
// 獲取用戶的關(guān)注列表
select fid from tb_user_followers where uid = xxx order by inverse_date limit 20; 
// 取用戶的粉絲列表.
select fid from tb_user_fans where uid = xxx order by inverse_date limit 20; // 獲

粉絲查詢和關(guān)注查詢從兩張表進行查詢。
由于需要保證拆分后的表大小不能超過200w,所以最后選擇的拆分的大小是每個主表128張分表。

數(shù)據(jù)遷移方案

首先是代碼的遷移,因為一個表變成了兩個表,所以底層變更如下:

  1. 關(guān)注需要更改為寫入到兩個表,取消關(guān)注刪除兩個表數(shù)據(jù)。
  2. 查詢分別從相應的表中查詢。
  3. 老數(shù)據(jù)需要同步到新表中。
    寫入的 sql 如下:
INSERT IGNORE INTO tb_user_followers_000 (uid,fid,from,create_date,inverse_date)
                SELECT uid,fid,from, create_date,inverse_date FROM tb_user_friends WHERE uid % 128 = 0;
                
INSERT IGNORE INTO tb_user_fans_000 (uid,fid,from,create_date,inverse_date) 
                SELECT fid,uid,from,create_date,inverse_date FROM tb_user_friends WHERE fid % 128 = 0;

但為了保證主從不能延遲過高,以及數(shù)據(jù)的完整性,我們選擇的導入方案如下:

  1. 需要保證業(yè)務讀寫正常,同時導數(shù)據(jù)又不要太慢,開的4個導數(shù)據(jù)進程按時間分批次導入。
  2. 導入的是上線前一天的所有數(shù)據(jù),上線當天將增量數(shù)據(jù)再次導入。
  3. 因為導入的都是增量數(shù)據(jù),所以上線后,需要將DELETE的sql通過腳本刪除新表中的數(shù)據(jù),這樣就保證了數(shù)據(jù)的完整性。

可能存在的問題

  1. 因為是粉絲關(guān)注表,如果突然某個人火了,某個表的增量將會非常大。
  2. 查詢粉絲的或者關(guān)注總數(shù)的查詢將需要循環(huán)查詢,解決方案,將這些數(shù)維護到一個表中。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容