这个相当明显的问题很少(找不到)可靠的答案。
我从200万行的表格中进行简单的选择。
select count(id) as total from big_table
我尝试此查询的任何计算机通常至少需要5秒才能完成。这对于实时查询来说是不可接受的。
我需要获取行的精确值的原因是稍后进行精确的统计计算。
遗憾的是,使用上一个自动增量值不是一个选项,因为行也会定期删除。
答案 0 :(得分:5)
在InnoDB引擎上运行时确实很慢。如section 14.5.7 of the MySQL 5.7 Reference Manual, “Restrictions on InnoDB Tables”中所述,第4点要点:
InnoDB 不保留表中的内部行数,因为并发事务可能会同时“看到”不同数量的行。要处理
SELECT COUNT(*) FROM t
语句, InnoDB 会扫描表的索引,如果索引不完全在缓冲池中,则需要一些时间。要快速计数,您必须使用自己创建的计数器表,并让应用程序根据插入和删除更新它。如果大概行数足够,则可以使用SHOW TABLE STATUS
。
建议的解决方案是计数器表。这是一个单独的表,其中包含一行和一列,具有当前记录计数。它可以通过触发器保持更新。像这样:
create table big_table_count (rec_count int default 0);
-- one-shot initialisation:
insert into big_table_count select count(*) from big_table;
create trigger big_insert after insert on big_table
for each row
update big_table_count set rec_count = rec_count + 1;
create trigger big_delete after delete on big_table
for each row
update big_table_count set rec_count = rec_count - 1;
您可以在此处看到fiddle,您应该在其中更改构建部分中的insert
/ delete
语句,以查看效果:
select rec_count from big_table_count;
您可以为多个表扩展它,可以为每个表创建一个表,也可以在上面的计数器表中为每个表保留一行。然后它将由列“table_name”键入。
如果您有多个并发会话插入或删除记录,上述方法会产生影响,因为他们需要等待彼此完成计数器的更新。
解决方案是不让触发器更新相同的单个记录,而是让他们插入新记录,如下所示:
create trigger big_insert after insert on big_table
for each row
insert into big_table_count (rec_count) values (1);
create trigger big_delete after delete on big_table
for each row
insert into big_table_count (rec_count) values (-1);
获得计数的方法变为:
select sum(rec_count) from big_table_count;
然后,偶尔(例如每天)你应该重新初始化计数器表以保持小:
truncate table big_table_count;
insert into big_table_count select count(*) from big_table;
答案 1 :(得分:-1)
你有索引吗?
ALTER TABLE big_table ADD INDEX id
您可以检查并尝试添加此