算大表的准确性

时间:2016-01-21 20:56:36

标签: php mysql

我有一个可以增长并拥有数百万行的mysql表。

我需要每次计算这些行,在同一页面中我可以为不同用户计算大约10次:

select count(id) from posts where user = ?

所以,为了避免这种情况,我正在考虑创建一个数据表,并在那里增加或减少这个数字以保持计数器。

update postscount SET number = number + 1  where user = ?
select number from postscount where user = ?

所以这个选择要快得多。

我的问题是,这是一个很好的做法,准确度如何,我有一个innodb表,它能保持准确的插入数量吗? (如果我有同时插入?)

谢谢你的朋友们!

4 个答案:

答案 0 :(得分:2)

如果id是主键(它应该!),并且自动递增+1并且您有索引iduser,那么您的第一个sql应该没问题。索引和密钥在SQL中很重要。

  

所以,为了避免这种情况,我想创建一个数据表并增加或减少这个数字以保持计数器。

仅当您在SQL中使用触发器(在第二个表上使用Update Trigger)时,而不是使用PHP。

您还可以在表格中添加一个新字段,例如postindex,然后您可以为新帖子中的每个用户计算个人数量并选择该字段(通过postindex DESC从用户订单中选择postindex)。

答案 1 :(得分:1)

不是为每个单独的用户计算ID,而是为了使用group by之类的

所有用户获取它
select count(id) 
from posts 
group by user;

根据您的评论,如果您计算每个用户登录的帖子,请确保您在WHERE条件(user)中使用的列已编入索引,并且对每个用户运行查询将没事的。但创造第二张桌子是我不会做的事情,并且不会以任何方式赢得更快。您必须为update执行两个语句,并获取number列。

同样,您可以按照我先说的那样获取所有用户的计数,然后将其缓存在应用程序端(缓存值通常为全局),然后在所有用户会话中,您可以使用相同的缓存数据而无需触发每次都有一个单独的查询。

答案 2 :(得分:1)

我不会说这是一种很好的做法,但这是一种常见做法。我过去必须做类似的事情,特别是在容易发生不成比例的系统中。确保包含时间戳,以便了解它的计数,并根据年龄刷新/丢弃它。这应该可以降低对数据库的影响,但是在执行此类操作时应该小心。其他解决方案可能是每X个时间为每个用户计算帖子。

答案 3 :(得分:1)

没有新表的解决方案

通常,MySQL每个查询只使用一个索引。 对于您的查询select count(id) from posts where user = ?,它可以是userid,但可能是user,因为它是where子句中的列。

在这种情况下,由于两列都已编制索引,您的查询将首先使用索引为用户选择行,但需要再次在id列上搜索(使用该列的索引) ,为了计算行数,因为count()只计算不为空的值。

鉴于此,您有2个选项(无需创建新表):

  1. 使用两列创建索引;
  2. 仅使用select中的一列。
  3. 选项1.显然是一个不好的选择。所以,我们使用选项2。

    鉴于此,由于我们必须按user过滤,我们会改变计数。 count(user)是一个选项,但您也可以count(1)。所以更好的选择是:

    select count(1) from posts where user = ?
    

    您可以通过让mysql向您解释查询来测试这两个选项,只需在其前面添加explain。并且,为了使您的结果不受查询缓存的影响,请在选择字后添加sql_no_cache。例如:

    explain select sql_no_cache count(user) from posts where user = 1
    
    explain select sql_no_cache count(id) from posts where user = 1
    
    explain select sql_no_cache count(id) from posts where user = 1
    

    比较结果。您可以检查使用哪些索引,mysql是否创建临时表等等。您可以为不同的用户制作,因为结果可能不同。

    新表的解决方案

    要创建一个新表,每次用户发布新帖时都会更新,为此,增益不会那么大,因为每次在帖子中插入一行(及其索引已更新)时,将在另一个表中插入/或更新新行(并更新其索引)。当然,另一个表会小很多,但每个插入都会慢一些。我没有这方面的数据。

    如果它不会那么快,因为MySQL的数据量无法管理。

    但是,您可以通过每X秒更新一次postcount表,每个Y用户帖子插入或使用交互等来改善这一点。在这种情况下,您可以更好地使用缓存(查询缓存,innodb缓存等),并不会遇到许多并发插入等问题。

    正如其他人发布的那样,上次更新行的时间戳列可能会在X秒后强制更新。

    可能每隔X秒进行一次更新,由cron / task完成,这将是一个很好的解决方案(在这种情况下,您不需要时间戳列),因为您可以利用查询缓存:启用后,mysql将每个选择查询存储在该缓存中,如果重复完全相同的查询(二进制比较)并且表没有更改,则mysql会立即返回第一个结果,而不会转到表。查看http://dev.mysql.com/doc/refman/5.7/en/query-cache.html了解详情。

    结论

    您有两个选择:1)通过仅使用列的一个索引来优化您的查询,或2)创建一个包含计数的新表。

    第一个选项更简单,可能适合您的系统。 100个用户并不是那么多。

    第二个选项更复杂,实施起来更复杂,并且会给你带来更好的性能。

    此外,通过改进Mysql服务器配置的配置,您可以提高系统性能。