在大中型項目中,在數據庫設計的時候,考慮到數據庫最大承受數據量,一般會把數據庫或者數據表水平切分,以下降單個庫,單個表的壓力。我這裏介紹兩個咱們項目中經常使用的數據表切分方法。固然這些方法都是在程序中使用必定的技巧來路由到具體的表的。首先咱們要確認根據什麼來水平切分?在咱們的系統(SNS)中,用戶的UID貫穿系統,惟一自增加,根據這個字段分表,再好不過。算法
方法一:使用MD5哈希數據庫
作法是對UID進行md5加密,而後取前幾位(咱們這裏取前兩位),而後就能夠將不一樣的UID哈希到不一樣的用戶表(user_xx)中了。數據庫設計
function getTable( $uid ){ui
$ext = substr ( md5($uid) ,0 ,2 );加密
return "user_".$ext;spa
}.net
經過這個技巧,咱們能夠將不一樣的UID分散到256中用戶表中,分別是user_00,user_01 ...... user_ff。由於UID是數字且遞增,根據md5的算法,能夠將用戶數據幾乎很均勻的分別到不一樣的user表中。設計
可是這裏有個問題是,若是咱們的系統的用戶愈來愈多,勢必單張表的數據量愈來愈大,並且根據這種算法沒法擴展表,這又會回到文章開頭出現的問題了。md5
方法二:使用移位路由
具體方法是:
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取前三位或者四位甚至更多位了。
兩種方法都是將數據水平切分到不一樣的表中,相對第一種方法,第二種方法更具擴展性。