SQL中哪个更快:许多MANY表与一个巨大的表相比?

时间:2011-07-17 18:20:39

标签: php mysql sql

我正在创建一个网站,我需要在sql中存储用户的活动(类似于stackoverflow中的收件箱)。目前,我和我的队友正在争论最有效的方法;到目前为止,我们已经提出了两种替代方法:

  1. 为每个用户创建一个新表,并使表名为itsusername_activity。然后,当我需要获取他们的活动(发布,评论等)时,我只需获取该表并查看其中的行...
    • 最后我会有 TON 表格
    • 可能更快
  2. 有一个名为activity的大表,其用户名为额外字段;当我想要他们的活动时,我只需从该表中获取行"...WHERE username=".$loggedInUser
    • 少桌,清洁
    • (假设我正确地索引表格,这还会慢吗?)
  3. 任何替代方法也将受到赞赏

7 个答案:

答案 0 :(得分:6)

  

“为每个用户创建一个新表...最后我将有一个TON表”

这绝不是使用关系数据库的好方法。

SQL数据库可以很好地应对数百万行(甚至更多),即使在商用硬件上也是如此。正如您已经提到的,您显然需要可用的索引来涵盖将在此表上执行的所有可能的查询。

答案 1 :(得分:3)

1号简直太疯狂了。你能想象去管理它,并看到所有这些表。

你能想象备份!或转储!很多人创造了表格......这会很疯狂。

为您提供一个好的索引,您可以轻松排序记录。

答案 2 :(得分:3)

这里我们谈谈MySQL。那么为什么制作单独的表会更快呢?

  • 查询缓存效率,来自一个用户的每个插入都不会为其他用户清空查询缓存
  • 记忆&分页,使用的表格适合缓冲区,未使用的数据很容易被加载

但正如管理方面所说,这里的所有人都说semms非常疯狂。但是在有很多表格的表演方面会增加mySQL中的另一个问题,你可能会运行我们的文件描述符,或者只是删除你的表缓存

在这里选择正确的引擎可能更为重要,例如 MyIsam 而不是Innodb,因为这是一个仅插入表。正如@RC所说,一个好的分区政策会修复内存和放大器。通过避免活动内存缓冲区中很少使用的数据的加载来实现分页问题。这应该通过智能应用程序设计来完成,默认情况下您可以避免加载所有活动历史记录,如果将其减少到最近的活动并将完整的历史记录表解析限制为批处理和高级屏幕,您将获得分区效果很好。您甚至可以尝试基于用户的分区策略。

对于查询缓存效率,您可以通过使用应用程序级缓存(如memcache)获得更大的收益,其中保存了每个用户的历史记录元素,并在每个新插入时清空它

答案 3 :(得分:1)

在某些情况下,第一个选项是,尽管不是严格的“关系方式”,稍微更好,因为它使您在增长时跨多个服务器分割数据库变得更加简单。 (这正是使wordpress.com能够扩展到数百万个博客的原因。)

关键是只对那些完全独立于用户的表格执行此操作 - 即永远不会一起查询。

在您的情况下,选项2最常见的情况是:您几乎肯定希望在某些时候查询所有用户或某些用户的活动。

答案 4 :(得分:1)

您想要第二个选项,并添加userId(可能还有一个用于userid,用户名等的单独表格)。

如果您在正确编制索引的字段上对该ID进行查找,则只需要log(n)个步骤来查找行。这根本不是什么。它会比选项1更快,更清晰,更好。选项1只是愚蠢。

答案 5 :(得分:1)

使用选项2,不仅索引用户名列,还要对该列进行分区(考虑散列分区)。对用户名进行分区将为您提供与第一个选项相同的好处,并让您保持理智。以这种方式对列进行分区和索引将提供基于username / user_key访问数据的非常快速有效的方法。在查询分区表时,SQL引擎可以立即丢弃它不需要扫描的分区,因为它可以根据查询的用户名值与该用户名驻留在分区中的能力来判断。 (在这种情况下,只有一个分区可以包含与该用户绑定的记录)如果您将来需要在多个服务器上对表进行分片,则分区不会妨碍该功能。

您还希望通过将username字段(以及与username相关的表中的任何其他元素)与user_key分隔到其自己的表中来规范化表。确保用户名表中user_key字段的主键。

答案 6 :(得分:0)

这主要取决于您需要检索值的位置。如果它是单个用户的页面,那么使用第一种方法。如果要显示所有用户的数据,则应使用单个表。使用多表方法也很干净但是在sql中如果单个表中的记录数非常高,则数据检索非常慢