社交网络应用程序数据库设计:如何改进此架构?

Posted

技术标签:

【中文标题】社交网络应用程序数据库设计:如何改进此架构?【英文标题】:Social web application database design: how can I improve this schema? 【发布时间】:2011-04-20 03:47:21 【问题描述】:

背景

我正在为诗人和作家开发一个社交网络应用程序,让他们可以分享自己的诗歌、收集反馈并与其他诗人交流。我在数据库设计方面几乎没有接受过正规培训,但我一直在阅读书籍、SO 和在线数据库设计资源,以尝试确保性能和可伸缩性而不会过度设计。

数据库是 mysql,应用程序是用 php 编写的。我还不确定我们是使用 ORM 库还是在应用程序中从头开始编写 SQL 查询。除了 Web 应用程序,Solr 搜索服务器和一些消息传递客户端可能会与数据库进行交互。

当前需求

我在下面汇总的架构代表了网站第一个版本的主要组件。最初,用户可以注册该站点并执行以下任何操作:

创建和修改个人资料详细信息和帐户设置 发布、标记和分类他们的文章 阅读、评论和“收藏”其他用户的帖子 “关注”其他用户以获取他们的活动通知 搜索和浏览内容并获取建议的帖子/用户(尽管我们将使用 Solr 搜索服务器来索引数据库数据并运行这些类型的查询)

架构

这是我在 MySQL Workbench 上为初始站点设计的内容。我对一些关系数据库的东西还是有点模糊,所以放轻松。

问题

    总的来说,有什么我做错了或可以改进的地方吗? 有什么理由不应该将 ExternalAccounts 表合并到 UserProfiles 表中? 我有什么理由不应该将 PostStats 表合并到 Posts 表中? 我是否应该扩展设计以包含我们在第二个版本中所做的功能,以确保初始架构能够支持它? 我能做些什么来优化 Solr 索引/性能/其他方面的数据库设计吗? 我是否应该在 Locations 表中使用更自然的主键,例如用户名而不是 UserID,或者邮政编码/区号而不是代理 LocationID?

感谢您的帮助!

【问题讨论】:

请不要将 SQL 查询放在应用程序的嵌入字符串中。请考虑改用存储过程等。请。 哦,抱歉,我会使用存储过程/在查询和应用程序的其余部分之间构建一些基本抽象。 可能会为首选类别等添加“UserPreferences”——无论是新表还是在 UserProfiles 中。 【参考方案1】:

总的来说,有什么我做错或可以改进的地方吗?

总的来说,我认为您当前的设置或架构没有任何重大缺陷。

我想知道的是您将其拆分为 3 个 User* 表。我得到了你想要的东西(有不同的用户相关的东西分开),但我不知道我是否会选择完全相同的东西。如果您计划仅显示站点上 User 表中的数据,这很好,因为在同一页面上不需要多次其他信息,但如果用户需要使用他们的真实姓名并显示他们的真实姓名(如John Doe 而不是 doe55),当数据变大时,这会减慢速度,因为您可能需要连接。将Preferences 分开似乎是个人选择。我不赞成也不反对。

您的多对多表不需要额外的 PK(例如 PostFavoriteID)。 PostIDUserID 的组合主要就足够了,因为 PostFavoriteID 从未在其他任何地方使用过。这适用于所有连接表

我有什么理由不应该合并 ExternalAccounts 表到 UserProfiles 表中?

与上一个一样。回答,我没有看到优势或劣势。我可能将两者放在同一个表中,因为NULL(或者更好的-1)值不会打扰我。

我有什么理由不应该合并 PostStats 表 进入 Posts 表?

我会使用触发器将它们放入同一个表中以处理ViewCount 表的增量

我是否应该扩展设计以包括 我们正在做的功能 第二个版本只是为了确保 初始架构可以支持吗?

您使用的是 normalsied 架构,因此可以随时进行任何添加。

我可以做些什么来优化 Solr 的数据库设计 索引/性能/其他?

不能告诉你,还没做过,但我知道 Solr 非常强大和灵活,所以我认为你应该做得很好。

我应该使用更自然的主键,比如用户名而不是 用户 ID,或邮政编码/区号,而不是 Locations 中的代理 LocationID 桌子?

这里有 很多 个线程在讨论这个问题。就个人而言,我更喜欢代理键(或另一个唯一的数字键,如果可用),因为它使查询更容易和更快,因为查找 int 更容易。如果您允许更改用户名/电子邮件/无论您的 PK 是什么,则需要大量更新。使用代理键,您无需费心。

我还要做的是在(最好通过触发器或程序 IMO 完成)添加诸如 created_atlast_accessed 之类的内容,以使一些统计信息可用。这确实可以为您提供有价值的统计数据

进一步提高性能的策略是内存缓存、计数器缓存、分区表等……当你真的被用户超越时,可以讨论这些事情,因为可能有东西/技术/技术/……非常针对您的问题。

【讨论】:

【参考方案2】:

我不清楚您的 User* 表发生了什么 - 它们的设置好像是 1:1 但图表反映了一对多(鱼尾纹符号)。

ExternalAccountsUserSettings 可以进一步规范化(在这种情况下,它们将是一对多!),这将为您提供更易于维护的设计 - 您无需添加更多列其他外部帐户或通知类型的架构(尽管这在性能方面可能不太可扩展)。

例如:

ExternalAccounts
    UserId int,
    AccountType varchar(45),  
    AccountIdentifier varchar(45)

将允许您以相同的结构存储 LinkedIn、Google 等帐户。 同样,可以使用以下结构轻松添加更多通知类型:

UserSettings
    UserId int,  
    NotificationType varchar(45),  
    NotificationFlag ENUM('on','off')

【讨论】:

以上是关于社交网络应用程序数据库设计:如何改进此架构?的主要内容,如果未能解决你的问题,请参考以下文章

社交网络好友列表、朋友圈、帖子分享的数据库设计[关闭]

构建社交网络类型应用程序的模式?

使用Memcached改进Java企业级应用性能:架构和设置

在社交网络设计中使用外键 - 好/坏?

安卓社交网络应用

社交产品后端架构设计