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万行慢计数的主要内容,如果未能解决你的问题,请参考以下文章