用户表id字段为unsign int最多可存42亿的记录
用户关系表关系字段左查询正反两向,用varchar英文编码 latin1 ,可存储6.5万多字符,按6万算,留5000给其他字段,每个用户id(int(10))加/共12个字符(如果id是从1开始,那么其实平均下来只有10/2+2=7个字符),那么就是60000/12=5000个,一共可以存储5000个上级用户数据,因为双向,所以单字段存2500个,所以当一个用户的上级关系超过2500以后就不能继续存储了,为了标示是否已经到了2500个,应该有个字段存储当前用户层级和上级数量,防止无限添加导致出错,或者需要每次都先做统计。总结:最多有2500层下线(不是2500个,每层都可以有无限个下线),如果用户id是从1开始实际可存储 60000/7/2 = 4285 层
要知道id为10的人有哪些下线:
首先,它自己的上线正关系字段:1/,加上自己的id就是1/10/
它的每个下线都有一个上线正关系字段,比如id为500的用户:1/10/200/
那么,要知道10的所有下线,只需要like '1/10/%'
要知道id为500的所有上线:因为它自己的上线反关系字段:200/10/1/,只需要直接取出就可以了
为了快速检索一个用户的1级或指定层级的所有下线,应当存储一个用户层级字段,这样要找到一个第2层用户的5层以内下线只需要:like '1/10/%' and level < 7
// 获取他的上线sys_user_ref
int depth = 0;
int leader_uid = 0;
String leaders = "";
String leaders_reverse = "";
if(Validator.isNotNullOrEmpty(user.getRefeerUserId())) {
SysUserRefEntity leader = sysUserRefDao.queryObject(user.getRefeerUserId());
depth = leader.getDepth();
leader_uid = leader.getUid();
leaders = leader.getLeaders();
leaders_reverse = leader.getLeadersReverse();
}
/**
* lbnnbs: 如果上线操过2500层则截断
* 因为操过2500层的上线本身的leaders就是已经截断过的了,所以可以直接截断上线的leaders的最高层uid就可以
*/
if(depth > 2500) {
leaders = leaders.substring(leaders.indexOf("/") + 1);
leaders_reverse = leaders_reverse.substring(0, leaders_reverse.lastIndexOf("/", leaders_reverse.length() - 2) + 1);
}
Map<String, Object> umap = new HashMap<String, Object>();
umap.put("uid", user_id);
umap.put("depth", depth + 1);
umap.put("leaders", leaders + leader_uid + "/");
umap.put("leaders_reverse", leader_uid + "/" + leaders_reverse);
sysUserRefDao.save(umap);