COUNT(*)与计数(col)在MySQL看人们如何使用COUNT(*)和计数(col),它看起来就像大多数人认为他们是同义词和只使用他们怎么样,虽然性能上有很大差异,甚至查询结果。同时,我们发现不同执行MyISAM和InnoDB引擎。

请注意:所有测试申请MySQL版本8.0.30,在后台,我跑每个查询三到五倍,以确保所有人都完全缓存在缓冲池(InnoDB)或文件系统(MyISAM)。

计数函数Innodb引擎:

让我们来看看以下系列的例子InnoDB引擎:

在这个InnoDB引擎,我们可以看到它需要一些时间COUNT (*)计数(val_no_null)表的行,进一步我们将看到,MyiSAM InnoDB表相比更快得到答案的感觉COUNT (*)

但是为什么我们不能只缓存的实际数量的行吗?InnoDB不保持一个内部表的行数,因为并发事务可能会“看到”在同一时间不同数量的行。因此,SELECT COUNT(*)语句只对当前事务数行可见。顺便说一下,我们可以使用模式信息立即得到大约在问题表的行数:

正如你所看到的并不是精确的行数。然而,有时一个粗略的计算可能就足够了。

让我们来看看数(val_with_nulls);

在那里,你可以看到我们有差异的结果COUNT (*)vs计数(val_with_nulls)

为什么?因为val_with_nulls不是定义为列非空可以有一些空值,所以MySQL必须执行表扫描。这也是为什么第二个查询结果是不同的

所以COUNT (*)计数(col)查询不仅可以大量的性能差异,还问不同的问题。

让我们有另一轮的疑问,让我们看看InnoDB成功地做COUNT (*),计数(val_no_null),计数(val_with_nulls)用同样的在哪里条款:

我们可以看到查询的性能是对这两种情况下,只有10%的差别,如果你仔细注意解释COUNT (*)查询,你会注意到使用索引。这意味着MySQL可以只使用索引,不碰其他表数据,这可能足以获得巨大的表的行数。

你可能想要使用列已经索引加速巨大的表的查询。

我们会有什么惊喜与计数(val_with_nulls) ?让我们来看看:

没有惊喜;我们可以看到查询的性能是相当甚至所有COUNT(*),计数(val_with_nulls)计数(val_with_nulls)。

计数函数MyISAM引擎:

现在让我们来看看COUNT()函数MyISAM引擎:

闪电的速度,我们所看到的!

因为这是MyISAM表,我们有缓存的表内的行数,这是MyISAM引擎是如何工作的。这就是为什么它可以立即回答COUNT (*)计数(val_no_null)查询。

请注意发动机的区别:InnoDB事务引擎,MyISAM事务性存储引擎。

但当谈到计数(val_with_nulls)MyISAM表我们可以看到这是一个慢InnoDB 7倍;巨大的差异。同时,我们可以看到相同的行为计数(val_with_nulls),因为值显然不会被考虑。MySQL优化器很好地在这种情况下,做一个全表扫描仅当它是必要的,因为列可以为空。

现在,让我们尝试更多查询MyISAM表使用WHERE子句:

正如您可以看到的,即使你有一个在哪里条款,性能COUNT (*)计数(col)可以明显不同。事实上,这个例子显示了一个五倍性能差异,因为所有的数据适合在内存中(为你的信息,因为它是MyISAM引擎,缓存数据的文件系统缓存级别)。IO-bound工作负载,你经常可以看到甚至100倍性能差异。

COUNT(*)查询可以使用覆盖指数尽管计数(col)不能。当然,您可以扩展指数(val_with_nulls id)又让查询索引覆盖,但我只会使用这个解决方案,如果你不能改变查询(即,它是一个第三方应用程序)或当列名的情况下查询是有原因的,和你需要一个非空值。

值得注意的是在这种情况下,优化器MySQL不做好优化查询。人们可以注意到(val_no_null)列不是零,所以计数(val_no_null)是一样的COUNT (*),所以查询可以运行作为一个index-covered查询。它不,查询执行行读取。

正如您可以看到的,扩展索引有助于提高计数(val_with_nulls)查询null值相比7倍左右计数(val_with_nulls)没有索引。但同时,你可以看到COUNT (*)慢变成0,6倍,可能是因为该指数变成了大约两倍的时间在这里。

最后,我想消除一些错觉(1)数(0)和计数。

正如你所看到的,查询的性能和解释都是一样的,它其实并不重要你什么号码将括号内COUNT()函数。可以是任何你想要的数量,它将完全等于COUNT (*)通过性能和实际产出的查询。

订阅
通知的
客人

2评论
最古老的
最新的 大多数投票
内联反馈
查看所有评论
Zonglei董

值得注意的是在这种情况下,优化器MySQL不做好优化查询。人们可以注意到(val_with_nulls)列不是零,所以计数(val_with_nulls)是一样的COUNT (*),所以查询可以运行作为一个index-covered查询。它不,查询执行行读取。

我认为它应该是“计数(val_no_null)”,而不是计数(val_with_nulls)