很多小的mysql表或一个大表

时间:2015-02-10 18:50:27

标签: mysql sql database performance structure

我有一个论坛,我有像 - >这样的属性 每个帖子,答案,评论都有followvoteupvotedownreportfavoriteview等。

哪种方法会更快更好地表现? 我期待数十亿favoriteviews等......就像youtube

接近一个

制作一张大表counter

counter_id | user_id | object_id | object_type | property

其中object_type = threadcommentanswer及其各自id来自表格threadscomments,{ {1}}

answers = propertyfollowvoteupvotedown

接近两个

制作reportfollowviews等个别表格

  • report

    views

  • view_id | user_id | object_id | object_type

    follows

2 个答案:

答案 0 :(得分:2)

对此没有单一的答案,它非常主观。

最常见的是,最好考虑设计的用例。在将这些字段添加到任何表之前,请仔细考虑这些字段的用途。并且不要认为你必须为每个表添加一个数字主键(" ID")。用于跟踪的表格很好,只有字段user id | object id | object type和主键中包含的所有三个字段。

你的代码不太可能会被用作youtube甚至堆栈溢出等性能限制。如果是这样的话,那么你很可能会在那时重建数据库。

然而,为了练习,请考虑使用数据的位置和方式......

我会有以下单独的表

<强>按照 用户提要,可能需要自己的表,因为它最常被从任何地方点击(有点像全局收件箱)。以下内容还应该有一些标记或时间戳来显示更改,以便在上次用户上线后发生更改时很容易评估.......

这是因为用户需要查看他们所遵循的内容,因为某些Feed和其他人需要查看有多少人关注过。但其他人不需要知道还有谁跟随。

投票,投票 那只是投票和+ - 旗帜。对此进行非规范化...即将用户在表中的个人投票存储起来,并在对象表的字段上存储针对对象的投票计数。这样,您只能检查单个用户的投票(他们拥有)以获取页面视图。从包含内容的同一行中检索计数。

再次。用户需要查看他们上/下投票的内容。你需要检查他们没有投票两次。重要的是最终的计数。因此,检查具有百万票数的对象不应该达到一百万行 - 只需一行。

专业提示:如果您经常更新包含大量内容的行,某些数据库引擎会表现不佳。所以考虑一下&#34;元数据&#34;所有对象的表。哪个商店计数如此。这使得元数据可以自由更新,即使内容不是。

<强>收藏 自己的表再次。 user id | object id | object type。如果您想向公众显示收藏数量,那么请针对该对象保持计数,不要在每个页面查看select count(*)

查看 为什么甚至存储这个?保持对对象的计数。如果您要存储历史记录,请确保为其添加时间戳并定期清除它。您不需要存储用户六个月前查看的内容。


作为一般观察,所有这些都是单独的表格,但上下投票除外。

您应该对计数进行非规范化,以减少服务器需要访问的数据量,以确定页面视图。最常见的是页面视图应该是最快的。任何形式的更新都可能会慢一点。


我提到收藏夹以及其他人不需要额外的主键字段。我的意思是他们有一个主键,而不是一个额外的字段。例如,收藏夹可以是:

CREATE TABLE favourites (
    user INT,
    object_type INT,
    object_id INT,
    PRIMARY KEY (user, object_type, object_id)
) 

根本没有理由拥有favorite_id字段。

答案 1 :(得分:1)

答案,第1部分:计划重新设计。

我能给你的最好建议是计划改变。你设计的第一个百万不会为3000万工作。 3000万的设计将无法生存到十亿。无论你在阅读这个帖子后做了什么,都可以持续30K行。

这是为什么?好吧,部分是因为你无法在一台机器上完成它。不要现在对你的数据库进行分片,但要记住你需要对它进行分片。那时,在一台机器上运行的大部分功能将无法在多台机器上运行,或者运行速度太慢。所以你必须重新设计。

让我指出10亿行的另一个方面。想想你在一年内将表格增长到1B行的速度有多快。它每秒超过30。这是不错的,直到你考虑到获得的峰值。

如果您的第二个十亿不会适合您已经布置的磁盘,会发生什么?

任何增长到十亿行的人都必须随时学习。教科书不去那里;手册不会去那里;只有销售人员去那里,但在支票清除后他们不会留下来。看看YouTube(等) - 几乎什么都不是#34;现成的#34;。

想想你需要雇佣多少智能设计师来达到10亿。

将列添加到十亿行表是很痛苦的,因此(1)提前计划,以及(2)设计一种在没有重大中断的情况下进行更改的方法。

答案,第2部分:一些提示

以下是我对这些想法的一些评论,以及处理了十亿行分片系统(不是YouTube,但类似的东西)的人的一些提示。

Normalize vs denormalize:我的座右铭:&#34;正常化,但不要过度正常化。&#34;你完成了一些工作后,你会明白我的意思。

一个表与多个表:两个具有基本相同的CREATE TABLE的表应该通常是一个表。 (当然,分片会违反这一点。)OTOH,如果你每秒需要数千UPDATE...view_count = view_count + 1,它就不会生存到十亿。但是,它可能会存活到一百万;然后计划改变。

最小化数据类型的大小 - 对一列使用MEDIUMINT而不是INT可以节省千兆字节。

不要使用OFFSET和LIMIT进行分页。 (我有一个解决方法的博客。)

尽可能批量插入。

使用InnoDB,您不想等待数小时的时间让REPAIR完成MyISAM表。

为下一个&#39;获取唯一ID的简单任务。 item可能是分片系统中的一个大问题。在重新设计该部分之前,请等待您更接近需要分片。不要将UUID用于十亿行表;他们表现不佳。所以,现在不要考虑UUID; 扔掉它们。

在您达到10亿之前很久,您将会遇到关于一台机器崩溃的噩梦。早点考虑复制,HA等。在你有大桌子之后设置这样的东西是痛苦的。