社交网站好友储存设计和实现(PHP+MySQL)
最近手头的一个网站新增社交功能,用户可以互加好友。
通常,对好友列表设计是新增一个好友,就往好友列表新增一行,当要查询一个用户好友
SELECT * FROM WHERE userid="100"
userid | nickname |
100 | 小智 |
101 | 小苍 |
102 | joker |
103 | JY |
table: users
user_id | friend_id |
100 | 101 |
100 | 102 |
100 | 103 |
101 | 102 |
101 | 103 |
table:friendlist
我的思路是:
将所有好友以键值对(键=userid,值=昵称)添加到数组中,因为userid在users表中是唯一,所以不用担心键会重复,再把数组序列化(serialize)存入到friend_id中,
当读取好友表时反序列化得到数组,形如:array('101'=>'小苍','102'=>'joker','103'=>'JY'),这表示用户100的好友,这样有一个好处是可以直接显示好友的昵称,而不用再查users表得到好友的昵称。
*这里强调一下,将数组插入数据库之前,一定要对数组序列化,否则当取出时,单个字符表示数组中的一个元素,而不是一组键值对。
userid | friend_id |
100 | a:3:{i:101;s:4:"小苍";i:102;s:5:"joker";i:103;s:2:"JY";} |
101 | a:2:{i:102;s:5:"joker";i:103;s:2:"JY";} |
table:friendlist
这样的好友存储设计在用户量百万级以上用户量效果很明显。
假设一个社交网站有110W用户,平均每个用户好友数为25,那么数据库就有110W * 25 = 2750W行,如果用户量和人均好友数上升,那么friendlist表行数超亿都是有可能的。
更如腾讯新浪用户亿级别的,好友数量几百上千,新增一个好友新加一行很显然是行不通的。
以数组形式存储好友,每个用户的好友列表只占一行,如果新增好友,只需往数组添加键值对就行了。这种方法有点事减少了数据库的开销,但是把添加键值对、序列化和反序列化的任务交给了web服务器,增加了服务器的开销,所以二者之间要有个权衡。
1.新增好友添加到数据库
//取出好友ID和名字 ,登录时已经把用户id和名称取出 $res = mysql_query("select friendList from friend where userid='$userid'"); $row = mysql_fetch_assoc($res); if($row == ""){ //如果好友列表为空 $arr = array($FromId['userid']=>$FromId['username']); $friends = serialize($arr); mysql_query("insert into friend values('$userid','$friends')"); }else{ //如果好友列表不为空,将‘ID’=》'用户名',插入到数组当中 $arr = unserialize($row['friendList']); if(array_keys($arr) == ""){//防止重复添加 $arr[$FromId['userid']] = $FromId['username'];//添加到数组中 $friends = serialize($arr);//插入数据库之前序列化 mysql_query("update friend set friendList = '$friends' where userid = '$userid'"); }
}
2.读取好友
$friendSql = mysql_query("select * from friend where userid='$row[userid]'"); $friendRow = mysql_fetch_array($friendSql); $friendList = unserialize($friendRow['friendList']);//反序列化