mysql - 需要有关主键选择的建议

标签 mysql sql database database-design relational-database

我正在为即将成为我的社交网站版本的数据库构建数据库。现在,我想存储 friend 关系,就像 Facebook 那样。我应该提到我为此使用 MySQL。

所以我正在考虑做这样的事情:

UserFriends
(
    UserFriendID SOME_DATA_TYPE NOT NULL AUTO_INCREMENT PRIMARY KEY,
    UserID BIGINT(20) UNSIGNED NOT NULL,
    FriendID BIGINT(20) UNSIGNED NOT NULL -- This is basically the same as UserID
)Engine=InnoDB;

现在,我正在寻找某种类型的数据类型用于该表的主键,因为我预计会有大量记录,并且我希望某种类型的索引来加快任何类型的速度我可能会在记录中进行查找。比如好友推荐功能等。

我愿意接受建议。在我看来,另一种选择,但管理起来要困难得多,是为每个用户动态创建一个单独的表,并将他们的 friend 存储在其中,但这对于代码管理来说是一场噩梦。

最佳答案

如果你做这样的事情

create table UserFriends
(
    UserFriendID SOME_DATA_TYPE NOT NULL AUTO_INCREMENT PRIMARY KEY,
    UserID BIGINT(20) UNSIGNED NOT NULL,
    FriendID BIGINT(20) UNSIGNED NOT NULL -- This is basically the same as UserID
) Engine=InnoDB;

那么您最终可能会得到如下所示的数据。

UserFriendID  UserID  FriendID
--
1             100     201
2             100     201
3             201     100

那个的问题应该是显而易见的。

如果您不需要知道谁加了谁好友,那么这样的事情会更有意义。 (标准 SQL,不是 MySQL。)

create table UserFriends (
    UserID BIGINT(20) UNSIGNED NOT NULL,
    FriendID BIGINT(20) UNSIGNED NOT NULL,
    primary key (UserID, FriendID),
    check (UserID < FriendID),
    foreign key (UserID) references users (UserID),
    foreign key FriendID references users (UserID)
);

主键约束保证单个“友谊”不会有多个相同的行。 check() 约束保证对于单个“友谊”,您不会有两行(仅 ID 号的顺序不同)。

但是由于 MySQL 不强制执行 check() 约束,因此您必须编写一个触发器来确保 UserID 小于 FriendID。

关于mysql - 需要有关主键选择的建议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12787479/

相关文章:

sql - 计算PostgreSQL中2个日期之间的工作时间

sql - 如何按字符串的特定部分排序?

sql - 对于具有大量数据的表,将数据类型从 varchar 更改为 nvarchar

php - mysql_insert_id 使用安全吗?

mysql - 包含 'AND' 和 'OR' 的 MS SQL 中断查询

php - 帮助更新成功 jquery ajax 上的关联元素

php - 搜索并比较两个表的行

database - liquibase 在两个数据库中使用 Maven

mysql - 类别和标签的数据结构

mysql - 需要稍微修改的 SQL 查询