mysql水平切分

 

在大中型項目中,在數據庫設計的時候,考慮到數據庫最大承受數據量,通常會把數據庫或者數據表水平切分,以降低單個庫,單個表的壓力。我這裏介紹兩個我們項目中常用的數據表切分方法。當然這些方法都是在程序中使用一定的技巧來路由到具體的表的。首先我們要確認根據什麼來水平切分?在我們的系統(SNS)中,用戶的UID貫穿系統,唯一自增長,根據這個字段分表,再好不過。

方法一:使用MD5哈希

做法是對UID進行md5加密,然後取前幾位(我們這裏取前兩位),然後就可以將不同的UID哈希到不同的用戶表(user_xx)中了。

 

function getTable( $uid ){
    $ext = substr ( md5($uid) ,0 ,2 );
    return "user_".$ext;
}

 通過這個技巧,我們可以將不同的UID分散到256中用戶表中,分別是user_00,user_01 ……    user_ff。因爲UID是數字且遞增,根據md5的算法,可以將用戶數據幾乎很均勻的分別到不同的user表中。

但是這裏有個問題是,如果我們的系統的用戶越來越多,勢必單張表的數據量越來越大,而且根據這種算法無法擴展表,這又會回到文章開頭出現的問題了。

方法二:使用移位

具體方法是:

 

public function getTable( $uid ) {
    return "user_" . sprintf( "%04d", ($uid >> 20) );
}

 這裏,我們將uid向右移動20位,這樣我們就可以把大約前100萬的用戶數據放在第一個表user_0000,第二個100萬的用戶數據放在第二個表user_0001中,這樣一直下去,如果我們的用戶越來越多,直接添加用戶表就行了。由於我們保留的表後綴是四位,這裏我們可以添加1萬張用戶表,即user_0000,user_0001 …… user_9999。一萬張表,每張表100萬數據,我們可以存100億條用戶記錄。當然,如果你的用戶數據比這還多,也不要緊,你只要改變保留表後綴來增加可以擴展的表就行了,如如果有1000億條數據,每個表存100萬,那麼你需要10萬張表,我們只要保留表後綴爲6位即可。

上面的算法還可以寫的靈活點:

 

/**
 * 根據UID分表算法
 * @param int $uid  //用戶ID
 * @param int $bit    //表後綴保留幾位
 * @param int $seed //向右移動位數
 */
function getTable( $uid , $bit , $seed ){
    return "user_" . sprintf( "%0{$bit}d" , ($uid >> $seed) );
}

 總結:

上面兩種方法,都要對我們當前系統的用戶數據量做出可能最大的預估,並且對數據庫單個表的最大承受量做出預估。

比如第二種方案,如果我們預估我們系統的用戶是100億,單張表的最優數據量是100萬,那麼我們就需要將UID移動20來確保每個表是100萬的數據,保留用戶表(user_xxxx)四位來擴展1萬張表。

又如第一種方案,每張表100萬,md5後取前兩位,就只能有256張表了,系統總數據庫就是:256*100萬;如果你係統的總數據量的比這還多,那你實現肯定要MD5取前三位或者四位甚至更多位了。

兩種方法都是將數據水平切分到不同的表中,相對第一種方法,第二種方法更具擴展性。。。

發佈了125 篇原創文章 · 獲贊 0 · 訪問量 6287
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章