如何加快InnoDB计数(*)查询?

时间:2015-02-21 15:45:24

标签: mysql sql count innodb

这里有很多类似的问题,但很多答案都说要强制使用索引,而且似乎并没有为我提速。

我想展示一个" live"我的网站上的计数器显示表格中的行数。有点像一些网站显示注册用户的数量,或者其他一些统计数据,实时" (即经常使用ajax或websockets更新)。

我的表有大约5M行。它的增长相当快,并且有大量的插入和删除。运行

select count(*) from my_table

需要1.367秒,这是不可接受的,因为我需要我的应用程序来获取每秒一次的新行数。

我尝试了这里提出的许多答案并将查询更改为:

select count(*) from my_table use index(my_index)

my_index Normal字段上的BTREE bigintstats。但实际上时间增加到了1.414秒。

为什么不使用索引加快查询速度,因为这里有很多答案会说明会这样做?

一些答案​​建议的另一个选项是在表上放置一个触发器,使另一个表中的列递增。因此,我可以创建一个my_table表,并且只要在stats中插入或删除行,就会在{{1}}表中触发增量或减少一列。这是唯一的其他选择,因为使用索引似乎不起作用吗?

编辑:以下是我尝试完成的事情类型的完美示例:https://www.freelancer.com。滚动到页面底部,您将看到:

enter image description here

这些数字每秒钟更新一次。

4 个答案:

答案 0 :(得分:1)

读取500万条记录并计算它们需要时间 - 无论是索引还是原始数据形式。

如果"快速和肮脏"解决方案是可以接受的,您可以使用元数据:

SELECT table_rows
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = <whatever> and TABLE_NAME = <whatever2>;

请注意,这可能会失去同步。

另一种可能性是将表分成更小的块。一个优点是,如果插入和删除往往是一个分区,您可以只计算它并使用其他分区的元数据。

在这种情况下,触发器可能会有所帮助,也可能无效,具体取决于insert / delete负载。如果你每分钟进行多次插入,那么触发器是一个简单的解决方案 - 一个很好的解决方案。如果您每秒进行数十次或数百次更改,则触发器的开销可能会降低服务器的速度。

答案 1 :(得分:1)

如果你的系统太繁忙以至于计数影响太大,那么INSERTing / DELETEing可能也会产生影响。改进INSERT / DELETE的一种方法是在批量生产中进行改进。而不是一次一个。

收集INSERT,最好是在应用中,但也可以选择在“暂存”中。表。然后,每隔一秒(或其他)使用INSERT..SELECT或(如果需要)INSERT..ON DUPLICATE KEY UPDATE将它们复制到真实表格中。 DELETE可以进入同一个表(带有标志)或单独的表。

COUNT(*)可以在批处理结束时完成。或者可以通过知道计数是多少来计算(以低得多的成本),然后通过临时表来改变它来调整。

这对您的应用代码来说是一个重大的动荡,所以除非您每秒有超过100个INSERT / DELETE的峰值,否则不要开始使用它。 (稳定的100 INSERT /秒=每年30亿行。)

有关&#34; staging table&#34;的详细信息,请参阅http://mysql.rjweb.org/doc.php/staging_table请注意,该博客主张在一对临时表之间进行翻转,以便最大限度地减少对它们的锁定,并允许多个客户共存。

答案 2 :(得分:0)

在后台运行一项工作,执行以下操作;然后用它的表来计算:

Loop:
    INSERT INTO Counter (ct_my_table)
        SELECT COUNT(*) FROM my_table;
    sleep 1 second
end loop

最糟糕的是,它会过时几秒钟。另请注意,INSERT和DELETE会干扰(读取:减慢)SELECT COUNT(*),因此&#34; sleep&#34;。

您是否注意到一些用户界面说&#34;大约120,000个东西&#34;?他们甚至使用更粗略的估计。但它对用户来说通常都足够好。

答案 3 :(得分:0)

  • 从Gordon Linoff建议的information_schema中获取不准确的值
  • 另一个不准确的行数来源是SELECT MAX(id) - MIN(id)
  • 创建表my_table_count,用于存储表my_table的行数并使用触发器更新

在许多情况下,您不需要准确的价值。谁在乎你是否显示36,400个用户而不是准确的36,454?

相关问题