工做筆記----數據庫分表

  1. 背景
    用於存儲用戶簽到數據表中的數據量超過1500萬條,在進行查詢時相對緩慢決定對其進行分表。
  2. 步驟前端

    a. 分析業務場景
    該表的使用者爲簽到用戶和運營人員。
    簽到用戶進行簽到時在表中記錄的相關信息:uid、時間、ip等。簽到用戶側對數據庫使用的基本特色是:單條記錄寫入,訪問量大,服務要求高可用。
    運營人員在前端經過uid查詢用戶的簽到信息,業務場景如:用戶投訴某天的簽到沒有統計。運營人員側需求的基本特色是:大量的批量分頁查詢需求,或許須要增長多種查詢方式。mysql

    b. 明確屬性查詢範圍
    該表的屬性查詢內容主要爲uid,即運營人員查詢用戶的uid。

    c. 方案設計:
    採用水平分表的方式,按照時間或uid進行分表。
    按照時間:好比半年
    優點:1.擴容簡單,只需按照時間增長表便可;2. 查詢的數據爲近期數據,只需在一個表中按照近期時間查詢便可;3.切分策略簡單;4.須要修改部分寫入和查詢的代碼:寫入操做須要按照時間更新,查詢操做須要根據查詢數據量進行多表查詢。
    劣勢:1.請求量不均,老是在新表寫入數據;2.當須要查詢用戶全部簽到數據時須要訪問全部表,時間慢;3.數據量不均,新增的表數據量會很是少。
    由於劣勢2不選擇此方案,有1000多個用戶簽到時間超過600天,證實存在一直簽到的用戶,那麼若按時間分配查詢他們的會比較慢。查詢邏輯會多寫一部分代碼。請求量和數據量均比較小,此兩項能夠不考慮
    按照uid:
    哈希法
    優點:1. 數據量均衡;2.請求量均衡。
    劣勢:1.擴容麻煩,若增長新表則需從新哈希,可能會致使數據遷移;2. 寫入操做須要更新按照uid哈希結果進行寫入,查詢操做須要按照uid哈希結果進行查詢。若增長新表則需修改代碼。
    選擇此方案:對3取餘擴容會在兩年後進行,不管採用什麼方案都會修改代碼
    範圍法
    優點:1.策略簡單;2.擴容簡單。
    劣勢:1.數據量不均;2.不方便增長新用戶,如今才4萬左右,若增長新用戶可能須要增長新表。sql

    最終結果:哈希法(對3取餘)
    採用此方案的緣由:
    數據分佈均勻,表中數據對3取餘後,各個字表中數據量分佈均勻,數據增加量分佈均勻,按照目前的增加速度大概兩年後每一個字表中的數據達到1000萬。
    mysql> select count(distinct uid),count(uid) from user_*** where uid % 3 = 0 and create_time > 1532238674000 and create_time < 1533189074000;
    +---------------------+------------+
    | count(distinct uid) | count(uid) |
    +---------------------+------------+
    | 14105 | 66926 |
    +---------------------+------------+
    1 row in set (14.55 sec)數據庫

mysql> select count(distinct uid),count(uid) from user_*** where uid % 3 = 1 and create_time > 1532238674000 and create_time < 1533189074000;
+---------------------+------------+
| count(distinct uid) | count(uid) |
+---------------------+------------+
| 13994 | 66237 |
+---------------------+------------+
1 row in set (14.46 sec)ui

mysql> select count(distinct uid),count(uid) from user_*** where uid % 3 = 2 and create_time > 1532238674000 and create_time < 1533189074000;
+---------------------+------------+
| count(distinct uid) | count(uid) |
+---------------------+------------+
| 13964 | 66300 |
+---------------------+------------+
1 row in set (17.93 sec)設計

mysql> select count(distinct uid),count(uid) from user_*** where uid % 3 = 0;
+---------------------+------------+
| count(distinct uid) | count(uid) |
+---------------------+------------+
| 346305 | 5288253 |
+---------------------+------------+code

mysql> select count(distinct uid),count(uid) from user_*** where uid % 3 = 1;
+---------------------+------------+
| count(distinct uid) | count(uid) |
+---------------------+------------+
| 345785 | 5324079 |
+---------------------+------------+ip

mysql> select count(distinct uid),count(uid) from user_*** where uid % 3 = 2;
+---------------------+------------+
| count(distinct uid) | count(uid) |
+---------------------+------------+
| 346966 | 5328743 |
+---------------------+------------+select

d. 執行方案
    (1)在保證用戶正常使用的前提下,對數據庫進行分表。須要在維持舊錶的同時,讓數據雙寫,同時寫入新表和舊錶,此時讓數據往新表導入。
相關文章
相關標籤/搜索