因为MySQL的MyISAM引擎在内部维护了一个计数器,当select count(*)其实就是拿到这个计数器的最新数值返回即可,而innodb却是要实时统计的。
那么,为什么innodb存储引擎不也维护一个计数器呢?
那是因为对于InnoDB这样的事务性存储引擎,存储准确的行数是不太现实的,因为多个事务可能同时发生,每个事务都有可能影响计数。 InnoDB不保留表中的行数,因为并发事务可能同时“看到”不同的行数。因此,SELECT COUNT(*)
语句只计算当前事务可见的行。
为了处理SELECT COUNT(*)
语句,InnoDB扫描表的索引,如果索引不是完全在缓冲池中,那么这将花费一些时间。
经过实践发现,不同的服务器配置下,当innodb表的行数达到数百万、数十万甚至数万的情况下,select count(*) 就会非常慢(需要十几秒甚至几分钟!),那么如何优化呢?
建议采用二级索引速度会比用主键索引更快。
在InnoDB引擎中,当我们通过二级索引统计数据的时候,无需扫描数据文件(二级索引存储指定字段的索引,实际的指向位置是主键索引。);而通过主键索引统计数据时,由于主键索引与数据文件存放在一起,所以每次都会扫描数据文件,所以主键索引统计没有二级索引效率高。
innodb表中除了主键ID之外,再找一个字段进行索引,然后在查询的时候使用select count(第二索引的字段),查询效率会大大提高。