COUNT(*)WHERE与SELECT(*)WHERE性能

时间:2011-08-14 01:09:19

标签: mysql

我正在建立一个论坛,我正在尝试计算每个用户提交的所有帖子。我应该使用COUNT(*) WHERE user_id = $user_id,还是如果我记录每个用户每次发帖并使用SELECT查询找到它的帖子数量会更快?

这会产生多大的性能差异?使用InnoDB和MyISAM存储引擎之间有什么区别吗?

7 个答案:

答案 0 :(得分:2)

如果您记录用户发布的帖子数量,那肯定会更快。

如果您在user表的posts字段上有索引,那么您也可以获得不错的查询速度。但是当posts表足够大时,它会损害您的数据库。如果您计划扩展,那么我肯定会建议在特定字段上保留用户帖子的记录。

答案 1 :(得分:0)

存储预先计算的值是一种常见且简单但非常有效的优化方法。

因此,只需添加用户发布的评论数量的列,并使用触发器或应用程序进行维护。

性能差异是:

  • 使用COUNT(*),您将始终拥有索引查找+结果计数
  • 使用附加字段,您将获得索引查找+返回数字(已有答案)。

在这种情况下,myisam和innodb之间没有显着差异

答案 2 :(得分:0)

存储帖子计数。无论存储引擎如何,这似乎都是一个可扩展性问题。您是否会在每次用户提交帖子时重新计算计数,或者您是否会在网络服务器范围之外的某处运行工作来处理此负载?你的帖子量是多少?您的服务器可以处理什么样的负载?我真的不认为存储引擎会成为故障点。我说存储价值。

答案 3 :(得分:0)

发布时的表现或计算表现的表现?从数据纯粹的角度来看,记录的计数与实际计数不同。您可以看到礼堂的前门,并添加进来的人并减去那些假,但如果有人潜入后门怎么办?如果您批量删除问题主题怎么办?如果您记录计数,则减慢一个帖子以计算并记录计数。对我来说,数据完整性就是一切,我每次都会计算(明星)。我刚刚在一个有3100万行的表上进行了测试,在一个索引列上有一个计数(星号),其值为424,887行--1.4秒(在我的P4 2 GB开发机器上,因为我有意为我的开发服务器供电,所以我得到了因慢速查询而受到惩罚 - 生产8核16 GB服务器,计数小于0.1秒)。您永远无法保护数据免受程序逻辑中的意外更改或错误的影响。计数(星号)是计数,它很快。如果count(star)很慢,则在其他查询中会出现性能问题。我做了星标,因为符号导致格式改变。

答案 4 :(得分:0)

如果您在user_id上有正确的索引,则COUNT(user_id)是微不足道的。

这也是语义上的正确方法。

答案 5 :(得分:0)

这实际上是那些“权衡”问题之一。

实际上,如果你的'帖子'表在'UserID'列上有一个索引,并且你真的只想返回帖子的用户数,那么使用基于此列的查询应该表现得非常好。

如果你有另一个表'UserPosts'用于e'g。,是的,查询该表会更快,但真正的问题是'你的'帖子'表真的那么大,你不能只是查询它这个数。两种方法的权衡显然是这样的:

1)具有单独的审计表,然后在添加,更新帖子时会产生开销 2)没有单独的审计表,然后直接查询表的开销

我的直觉总是设计一个系统来以合理的标准化方式记录数据。我永远不会根据以下事实制作表格:为了报告目的而获取一些数据可能会更快。我只会创造它们,如果需要的话,那么必须将它们合并,我会把它合并。

在一天结束时,我认为除非您的“帖子”表格大得多(即超过几百万条记录,否则查询它以获取不同的用户数量应该没有问题,假设它已编入索引正确的,即放在'UserID'列上的索引。

如果您纯粹将这些信息用于显示目的(即用户jonny已经发布了73次),那么很容易从数据库中获取信息一次,缓存它,然后更新它(缓存),何时或是否发生变化检测。

答案 6 :(得分:0)

有一大堆权衡,所以没有人可以给你正确的答案。但这是其他人没有提到过的方法:

您可以使用“select where”查询,但将结果缓存在更高层(例如memcache)。所以你的代码看起来像:

count = memcache.get('article-count-' + user_id)
if count is None:
    count = database.execute('select ..... where user_id = ' + user_id)
    memcache.put('article-count-' + user_id, count)

,当用户发布新帖时,您还需要

memcache.delete('article-count-' + user_id)

这在经常使用文章计数时效果最好,但很少更新。它结合了高效缓存的优势和规范化数据库的优势。但如果很少需要文章计数(在这种情况下,是否需要优化?),这不是一个好的解决方案。另一个不合适的案例是经常需要某人的文章计数,但它几乎总是一个不同的人。

这种方法的另一个优点是您现在不需要添加缓存。您可以使用最简单的数据库设计,如果事实证明缓存此数据很重要,请稍后添加缓存(无需更改架构)。

更一般地说:您不需要在数据库中缓存。你也可以在你的数据库周围放一个缓存。我用java做的事就是在ibatis级别使用缓存,例如。