在實際的應用場景中,當一個單表的數(shù)據(jù)量過億時寫入和查詢的壓力就會倍增,拆表在一定程度上是解決數(shù)據(jù)庫單表瓶頸的方案之一,
在本次要拆分的表中有以下特征:
- 單表已過2億
- 表數(shù)據(jù)量每天增量50萬左右
- 表結(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ù)遷移方案
首先是代碼的遷移,因為一個表變成了兩個表,所以底層變更如下:
- 關(guān)注需要更改為寫入到兩個表,取消關(guān)注刪除兩個表數(shù)據(jù)。
- 查詢分別從相應的表中查詢。
- 老數(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ù)的完整性,我們選擇的導入方案如下:
- 需要保證業(yè)務讀寫正常,同時導數(shù)據(jù)又不要太慢,開的4個導數(shù)據(jù)進程按時間分批次導入。
- 導入的是上線前一天的所有數(shù)據(jù),上線當天將增量數(shù)據(jù)再次導入。
- 因為導入的都是增量數(shù)據(jù),所以上線后,需要將DELETE的sql通過腳本刪除新表中的數(shù)據(jù),這樣就保證了數(shù)據(jù)的完整性。
可能存在的問題
- 因為是粉絲關(guān)注表,如果突然某個人火了,某個表的增量將會非常大。
- 查詢粉絲的或者關(guān)注總數(shù)的查詢將需要循環(huán)查詢,解決方案,將這些數(shù)維護到一個表中。