新特新解读 | MySQL 8.0 对 count(*)的优化

2 02 2 年我接触到一个项目。
该城市的一家公司使用 MySQL 5 .7 版本,使用 count() 对数据库中的某个表进行计数。
我当时很困惑为什么他们不使用 selectCount() 而是直接写 count() 。
后来我发现在MySQL 5 .7 中,count()的性能不太好。
他们可能认为这样写更容易。

但是到了2 02 2 年,听说MySQL 8 .0出来了,那个版本对count()做了很大的优化。
首先,它取消了 sql_calc_found_rows 语法。
在8 .0中不再推荐使用这种语法,因为它性能较差,并且会导致主从架构中数据不一致。

然后,MySQL8 .0优化了count()的执行计划成本计算。
例如,对于表的主键索引扫描,query_cost为8 .0比5 .7 低约5 0%。
这是因为8 .0在I/O成本估算上更加准确,优化器策略更倾向于使用索引覆盖扫描来避免表回操作。

后来才知道MySQL8 .0推荐的标准写入方法是selectCount()。
这种写法在大多数场景下都有足够的性能,并且不需要维护额外的逻辑。

我对比了优化前后的执行计划。
5 .7 的query_cost很高,而8 .0的query_cost低很多。
这就是性能提升的原因,在8 .0中,执行count()时更有可能直接使用索引元数据,而不是逐行读取数据。

当然,还有模拟计数器、近似值和特殊表结构等选项,但不是全部有你的极限。

所以,我现在的建议是,如果你使用的是MySQL8 .0,直接使用selectCount()就足够了,尤其是当表数据量不是特别大的时候。
另外,充分利用索引覆盖率,避免全表扫描,监视执行计划并考虑缓存策略。
这样,你的数据库性能会更好。

MySQL 导致 CPU 消耗过大,如何优化

哎呀,说到MySQL巨大的CPU消耗问题,真是老生常谈了。
我多年来一直在问答论坛上工作,看到太多人对此感到头疼。
用户空间CPU消耗主要由大量TPS、函数调用、排序、类型转换、逻辑I/O访问等各种逻辑操作引起。
我记得以前有一个项目,由于请求很大,CPU像一根火棒一样旋转。

首先我们需要分析处理器消耗的来源。
用户空间的CPU消耗。
让我举个例子。
有一家客户公司。
他们的系统每天必须处理数百万条数据。
因此,CPU 使用率仍然很高。
经过检查,发现是排序操作过多,导致CPU负载过高。

接下来我们来说说优化策略。
首先,减少I/O操作量,这取决于优化SQL查询和使用索引,例如将一些复杂查询拆分为多个简单查询并减少扫描的行数来减少I/O操作次数。
然后提高I/O处理能力,例如添加缓存、使用固态硬盘等快速存储设备,或者扩展磁盘资源。

我们来谈谈减少逻辑运算的数量。
这种情况并不少见,比如不使用数据库中的复杂功能,而将操作留给应用服务器。
它还减少了排序操作并使用索引来获取有序数据。
我记得在一个朋友的项目中,因为禁止类型转换,所以CPU负载立即下降。

优化索引和表结构也是关键。
明智地设计索引以避免不必要的表扫描。
对大表进行分区,并使经常访问的小字段变得冗余。
SQL的编写方法也发生了变化,允许充分利用现有索引并避免复杂的 JOIN、ORDERBY 和子查询。

减少请求数量也很重要。
使用缓存降低数据粒度,缓存经常访问的静态数据。
优化应用逻辑,去除不必要的重复请求。
我已经遇到过这种情况。
因此,请求数量减少了 3 0%。

最后,如果以上方法都不起作用,您可能需要考虑硬件升级,例如升级CPU或增加CPU核心数。
但老实说,在升级硬件时,您需要小心。
一般来说,在考虑这一点之前,您应该尽可能地优化软件。

预期的效果是提高吞吐量(TPS)、减少查询响应时间、减少慢查询,提高系统整体性能,特别是在高并发场景下。

注意。
优化索引时,需要平衡正回报和维护索引的开销。
数据类型的选择应遵循“够用”的原则,避免过度使用大字段。
硬件升级应被视为最后的手段,并且只有在软件级别完全优化之后才可以。
最终,正如我所说,优化是一个长期的过程,需要慢慢进行。