mysql 250万行慢计数

Posted

技术标签:

【中文标题】mysql 250万行慢计数【英文标题】:mysql 2.5M rows slow count 【发布时间】:2013-11-06 17:20:49 【问题描述】:

有一个带有id(主键)和hash(索引)的简单mysql表。其他一些列(varchar / int),但不需要对它们进行查询。

我的总表大小约为 350MB,有 250 万行。

SELECT COUNT(*) FROM table LIMIT 1;

大约需要 0.5 - 1 秒。我的 innodb 缓冲区设置为 1GB。我也尝试过变体(没有改进),例如:

SELECT COUNT(id) FROM table LIMIT 1;

SELECT COUNT(*) FROM table WHERE id > 0 LIMIT 1;

一个

SELECT * FROM table WHERE id = 'x' LIMIT 1;

将在 1 毫秒内返回(本地 mysql)。任何改善慢计数(0.5 - 1s)的技巧将不胜感激。

【问题讨论】:

【参考方案1】:

您可以找到简要说明here。简而言之,innodb 必须进行全表扫描才能计算所有行(没有 where 子句,它会利用索引)。 另见this answer。

顺便说一句,我看不出在您的查询中使用 LIMIT 1 有什么意义。由于没有group by 子句,它总是返回一条记录。

【讨论】:

但是由于我只使用主键,它不应该使用内存,因为它不需要键吗?我什至在 1GB inno db 缓冲区(4gb ram 机器)上进行了测试。 EXPLAIN 是你的朋友。在您的语句中使用EXPLAIN SELECT ... 并验证是否使用了索引。如果没有,你可以通过SELECT COUNT(id) FROM table USE INDEX (PRIMARY)强制使用【参考方案2】:

前段时间我发现,MyISAM 表使这些操作更快。但并不是所有的表和架构都可以是 MyISAM。检查您的架构,也许您可​​以将此表切换到 MyISAM。

也使用COUNT(1) 代替COUNT(*)

还有另一种技巧。创建触发器并将计数保存在单独的位置。创建counter_table 和以下触发器:

DELIMITER //

CREATE TRIGGER update_counter AFTER INSERT ON table_name
FOR EACH ROW
BEGIN
    UPDATE counter_table
    SET counter = counter + 1
END;

【讨论】:

以上是关于mysql 250万行慢计数的主要内容,如果未能解决你的问题,请参考以下文章

如何增强对数百万行表的 MySQL 查询?

对超过百万行进行排序的分组

基于 R 中的字段的运行计数

如何优化一个函数,该函数包含for循环和数据帧中的2000万行

R中大数据的计数算法

Django Rest Framework 分页极慢计数