我目前正在设计一个项目,我需要 DBA 的专业建议。
我的项目将采用类似于堆栈交换网站中使用的投票系统。我有用户和内容片段,用户可以为他们喜欢或不喜欢的内容片段投票。请注意,我将在提要列表上有投票上/下选项,所以如果我加载 30 个内容片段,我还需要加载用户对每个片段的投票数据,因为如果用户已经,上/下按钮应该高亮已投票支持特定作品。换句话说,我希望votes桌子上的负载很大。我在想这样的基本结构:
表users (user_id, ...),表content (content_id, ...),表votes (vote_id, user_id, content_id, datetime, vote)。但是,我对这种设计表示怀疑。
假设我有 10k 个用户和 1k 个内容片段。table 中有多达 1000 万条记录votes。如果我开始考虑扩大规模,我可以想象出一个大问题。内容不会去任何地方,旧的投票也是如此,所以网站运行的时间越长,表中的记录就越多,运行速度就越慢。
假设几年后我将拥有 100k 用户和 20k 内容块。这多达 20 亿条记录。我知道并不是每个用户都会对每个内容块进行投票,但问题很明显 - 该设计有一个限制(限制我的意思是当行数达到某个点时选择查询会很慢)。
所以我的问题是:
votes表上的选择查询会变慢,我该怎么做才能加快速度?votes表推荐什么样的索引?我需要一个简单的双字段索引 ( user_id, content_id) 是否正确?recent_votes表格的东西,它会保存重复的数据,但仅在最后说 24 小时内,大多数负载都会继续进行,如果用户想要一些较旧的数据,他会用更大更慢的表来处理所有选票吗?这有任何意义吗?我真的很想从一开始就做正确的事情,所以在几年内我不会以一个缓慢的网站结束。感谢您的时间。
该设计真的有限制吗?如果有,如何处理?1.1. 如果投票表上的选择查询变得越来越慢,我可以采取什么措施来加快速度?
我认为票数可能不是问题。这些问题在一定程度上与您的索引能力、数据库如何进行缓存等问题有关。适用标准性能调整,但这实际上并不是您的设计本身。如果您遇到无法让您的设计足够快地运行的情况,我将在下面详细回答您要考虑的事项。
有没有更好的方法来设计这种关系?
并不真地。
我如何缓存该数据?或者是否需要适当的索引?
在这种情况下,我的偏好是一开始不使用缓存,然后在需要时实现缓存层。缓存层可能包括 memcached 之类的东西,或者您可以在 Mongo 等 NoSQL 解决方案上构建一个缓存层。那时,您可以考虑优化最大问题的领域。
您会为投票表推荐什么样的索引?我需要一个简单的双字段索引(user_id,content_id),这是正确的吗?
我知道 MySQL 和 PostgreSQL 的不同足以使跨数据库在这里有些危险,但我认为您需要两个索引,一个在 content_id 上,一个在 user_id 上。我这样想是因为按 user_id 和 content_id 聚合可能是不同的查询,并且这些是不同的连接条件。
大部分负载将在最近的内容片段上进行,也许我应该创建类似centre_votes 表的内容,该表将保存重复的数据,但仅在最后24小时内进行,并且大多数负载将在其上进行,如果用户想要一些数据,则年纪大了,他会用更大、更慢的桌子与所有选票一起工作吗?这有任何意义吗?
请记住,数据库经常很好地缓存最近的内容片段。我希望 MySQL 也能做到这一点。如果实在不行就用 PostgreSQL 代替。不要自己将其缓存在数据库中。
如果你碰壁了该怎么办取决于你的数据库选择。如果您使用 MySQL,传统的答案是查看类似 memcached 的东西或在 NoSQL 数据库中创建缓存层。如果您使用 PostgreSQL,您可以获得这些选择以及 Postgres-XC 之类的功能,它使您能够在 OLTP 环境中进行 Teradata 式的横向扩展和集群。