SNS 数据库设计

本文节选自《Netkiller Architect 手札》

4.21. SNS 数据库设计

这里讲解SNS交友社区的数据库设计与实现

我们要实现下面几个功能

  1. 朋友之间的关系,多对多关系
  2. 朋友之间的维度,如3度4度....
  3. 朋友的查找
		CREATE DATABASE `sns` /*!40100 COLLATE 'utf8_general_ci' */		

4.21.1. people 表

people 是存储人,你可以用为user,member都可以

			CREATE TABLE `people` (
	`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
	`name` VARCHAR(50) NOT NULL,
	PRIMARY KEY (`id`)
)
COMMENT='Social Network Site - Six Degrees of Separation - http://www.netkiller.cn'
COLLATE='utf8_general_ci'
ENGINE=InnoDB;			

存储具体的这人

4.21.2. firend 表

这个表的功能主要是维持朋友之间的关系网,这里使用了多对多方式并且使用外键防止产生脏数据。

			CREATE TABLE `friend` (
	`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
	`people_id` INT(10) UNSIGNED NOT NULL,
	`friend_id` INT(10) UNSIGNED NOT NULL,
	`ctime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
	PRIMARY KEY (`id`),
	UNIQUE INDEX `unique` (`people_id`, `friend_id`),
	INDEX `FK_firend_people` (`people_id`),
	INDEX `FK_firend_people_2` (`friend_id`),
	CONSTRAINT `FK_firend_people` FOREIGN KEY (`people_id`) REFERENCES `people` (`id`),
	CONSTRAINT `FK_firend_people_2` FOREIGN KEY (`friend_id`) REFERENCES `people` (`id`)
)
COMMENT='Social Network Site - Six Degrees of Separation - http://www.netkiller.cn'
COLLATE='utf8_general_ci'
ENGINE=InnoDB;			

4.21.3. 演示

首先初始化用户数据

			INSERT INTO `people` (`id`, `name`) VALUES
	(1, 'Neo'),
	(2, 'Luke'),
	(3, 'Jack'),
	(4, 'Joey'),
	(5, 'Jam'),
	(6, 'John');			

建立朋友之间的关系

			INSERT INTO `friend` (`id`, `people_id`, `friend_id`) VALUES
	(1, 1, 2),
	(2, 1, 3),
	(3, 1, 4),
	(4, 1, 5),
	(5, 1, 6),
	(6, 2, 1),
	(7, 2, 3);			

现在就可以查找你的朋友了

			select people.* from friend, people where friend.people_id = 1 and friend.friend_id = people.id;			

查找朋友的朋友就比较麻烦了,必须使用递归方法,一层一层查下去,反复执行SQL效率是很低的,所以我们准备了第三张表。

4.21.4. network 表

关系网表,主要功能是弥补firend表,用于快速检索(在不使用递归的情况下)

			CREATE TABLE `network` (
	`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
	`people_id` INT(10) UNSIGNED NOT NULL,
	`following_id` INT(10) UNSIGNED NOT NULL,
	`friend_id` INT(10) UNSIGNED NULL DEFAULT NULL,
	`degrees` VARCHAR(250) NOT NULL,
	`ctime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
	PRIMARY KEY (`id`),
	UNIQUE INDEX `unique` (`people_id`, `friend_id`, `following_id`),
	INDEX `FK_firend_people` (`people_id`),
	INDEX `FK_firend_people_2` (`friend_id`),
	INDEX `FK_friend_people_following_id` (`following_id`),
	CONSTRAINT `FK_firend_people` FOREIGN KEY (`people_id`) REFERENCES `people` (`id`),
	CONSTRAINT `FK_friend_people_following_id` FOREIGN KEY (`following_id`) REFERENCES `people` (`id`),
	CONSTRAINT `FK_friend_people_friend_id` FOREIGN KEY (`friend_id`) REFERENCES `people` (`id`)
)
COMMENT='Social Network Site - Six Degrees of Separation - http://www.netkiller.cn'
COLLATE='utf8_general_ci'
ENGINE=InnoDB;			

following 一个朋友, Neo following Jam

			INSERT INTO `people` (`id`, `name`) VALUES
	(1, 'Neo'),
	(2, 'Luke'),
	(3, 'Jack'),
	(4, 'Joey'),
	(5, 'Jam'),
	(6, 'John');

INSERT INTO `network` (`people_id`, `following_id`, `friend_id`, `degrees`) VALUES ( 1, 5, NULL, '1.5');			

之前Neo已经 following Jam,接下来查找Jam的朋友,现在Neo following John, John 是 Jam 的朋友,friend_id = NULL 表示 Jam 尚未有朋友

			select * from network where people_id=1 and friend_id = 5;

INSERT INTO `sns`.`network` (`people_id`, `following_id`, `friend_id`, `degrees`) VALUES ('1', '6', '5', '1.5.6');			

Neo following Joey, Joey 是 Luke 的朋友, 所以 Luke可能是 Neo的朋友

			INSERT INTO `sns`.`network` (`people_id`, `following_id`, `friend_id`, `degrees`) VALUES ('1', '4', '2', '1.2.4');			

查询不同维度下的所有好友,查询出的用户ID需要处理。

			select * from network where people_id=1 and degrees like "1.%";
select * from network where people_id=1 and degrees like "1.2%";
select * from network where people_id=1 and degrees like "1.2.%";			

至此社区管理网就建立起来了

上面的例子演示了 people_id=1 即 Neo 的关系网

原文发布于微信公众号 - Netkiller(netkiller-ebook)

原文发表时间:2016-10-10

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏测试开发架构之路

分分钟搞懂union与union all

SQL UNION 操作符 UNION 操作符用于合并两个或多个 SELECT 语句的结果集。 请注意,UNION 内部的 SELECT 语句必须拥有相同数量的...

3399
来自专栏Java架构师历程

Mysql查询事例1

id  INT(10)  NOT NULL  UNIQUE  PRIMARY KEY  ,

1092
来自专栏菩提树下的杨过

温习sql语句中JOIN的各种操作(SQL2005环境)

温习sql语句中JOIN的各种操作(SQL2005环境) 为了方便测试,先建二个基本表T_Employee(员工表),T_Region(地区表) Sql语句...

1756
来自专栏Java后端生活

MySQL(七)DQL之分组查询

1565
来自专栏数据分析

[数据库基础]——图解JOIN

一、概要 JOIN对于接触过数据库的人,这个词都不陌生,而且很多人很清楚各种JOIN,还有很多人对这个理解也不是很透彻,这次就说说JOIN操作。 图片是很容易被...

3409
来自专栏编程之路

学生请假系统设计

需求分析:学生日常请假出入校门,学生向教师请假,教师在手机中提交请假信息,提交后可按请假时间出校门。教师可查看所有学生请假历史,统计分析,同时家长会看到自己孩子...

4785
来自专栏Java后端生活

MySQL(九)DQL之子查询

1478
来自专栏小古哥的博客园

常用SQL语句集合

一、数据定义 1、创建新数据库:CREATE DATABASE database_name 2、创建新表:CREATE TABLE table_name (c...

2946
来自专栏cmazxiaoma的架构师之路

一个麻瓜的自我反思之SQL语句基础练习

2863
来自专栏你不就像风一样

Mysql字段名与保留字冲突导致的异常解决

742

扫码关注云+社区