Code前端首页关于Code前端联系我们

MySQL 性能很差吗?死代码问题解决了吗?

terry 2年前 (2023-09-26) 阅读数 49 #数据库

MySQL 存储过程、函数和触发器是开发人员经常接触的三个术语。但是,这三个过程可能会对数据库性能产生严重影响,尤其是当函数显示“死”代码时。另外两个进程受到影响。以下是作者运行的一些基本测试,以便通过比较更好地衡量三者对数据库性能的影响。

触发器和存储函数影响性能的一个重要原因是函数的“死”代码。虽然所有开发人员都知道“死”代码(从不执行的代码)不应出现在代码行中,但可能不清楚单行“死”代码会对性能产生多大影响。

“死”代码会显着降低运行函数、存储函数和触发器的响应时间,因此必须仔细清理不必要的代码,以下是具体示例: 分析 MySQL 存储函数函数

比较下面是四个简单的存储函数(MySQL 5.7):

函数 1

MySQL性能差?死代码牵连问题解决了吗?

该函数只是声明一个 r 变量并返回它的值,这是一个虚函数。

函数2

MySQL性能差?死代码牵连问题解决了吗?

该函数调用另一个函数levenshtein_limit_n(计算levenshtein距离)。但是,由于 IF 1=2 条件永远不会为真,因此该代码永远不会执行,函数 1 的返回结果也是如此。

Funktion 3

MySQL性能差?死代码牵连问题解决了吗?

Funktion 3 看起来很复杂,总共有四个条件,但由于这些条件永远不成立,所以它也是一个“死”代码调用,其结果与函数 2 和函数 1 相同。

函数4

MySQL性能差?死代码牵连问题解决了吗?

这个函数和函数3的情况一样,selectdoes_not_exit依然存在。没有被驱动。

虽然所有函数最终返回的r值都是0,但这四个函数的性能差别很大。为了衡量性能变化,我们使用基准函数来测试性能。运行同样一百万次后,四个函数的性能结果如下:

MySQL性能差?死代码牵连问题解决了吗?

我们看到 func 1 只需要花费 1.75 秒,func 2 有一个死代码调用,需要花费 2.45 秒,而func 3 (有四个从不执行的死代码调用)的运行速度几乎比 func 1() 慢 3 倍,并且 func 3_nope() 的响应时间与 function 3() 完全相同。 可视化对函数的所有系统调用

要了解函数调用期间发生的情况,我们可以使用 Performance_schema/sys 模式通过 ps_trace_thread() 过程创建跟踪。?我运行 select func1()) 的时间为 10 秒,然后它运行序列并创建一个点文件:

MySQL性能差?死代码牵连问题解决了吗?

我对上述所有函数重复了这些步骤,然后创建了命令图。

结果如下:

Func1():

MySQL性能差?死代码牵连问题解决了吗?

Func2():

MySQL性能差?死代码牵连问题解决了吗?

Func3():

MySQL性能差?死代码牵连问题解决了吗?

正如我们所见,对于每个“if_ not sp/jump”检查,之后哪个表被打开。因此,解析“IF”条件会对性能产生影响。

对于MySQL 8.0,我们还可以看到该存储过程的MySQL源码文档,记录其实现如下:

  • 流量分析优化;
  • 生成代码后,优化低级sp_instr指令。

优化主要集中在两部分:

  • 死代码去除;
  • 快捷键。

这两个优化一起执行,因为它们都在表示问题生成代码的图中包含流量分析。实现这些优化的代码是 sp_head::optimize()。

但是,这并不能解释为什么要执行“开表”,所以我向官网提交了一个bug - MySQL Bug #91585。

MySQL bug #91585 链接:

https://bugs.mysql.com/bug.php?id=91585“死”代码如何影响触发器性能?

当然,如果我们不运行太多操作,我们可能不会注意到这些性能差异,但它确实在触发器内部产生影响。假设一个表有一个触发器,每次更新表时都会执行触发器来更新字段。例如,假设我们有一个名为“form”的表,我们只需要更新其创建日期:

MySQL性能差?死代码牵连问题解决了吗?

现在我们创建一个调用虚拟函数 func1() 的触发器:

MySQL性能差?死代码牵连问题解决了吗?

请记住:重复更新不会更改新结果,因为我们在触发器中没有执行任何操作。

MySQL性能差?死代码牵连问题解决了吗?

如果再添加一个虚拟触发器,即使触发器不执行任何功能,它也会使额外负载加倍,从而导致速度变慢:

MySQL性能差?死代码牵连问题解决了吗?

现在使用 func3(它具有“死”代码,但功能是与 func1 相同):

MySQL性能差?死代码牵连问题解决了吗?

如果我们在触发器内执行函数 func3 中的代码(而不是调用该函数),则会加快更新速度:

MySQL性能差?死代码牵连问题解决了吗?内存分配

即使代码从未执行, MySQL 仍然需要分析来解析每次执行中的存储过程或触发代码,并提前为其保留足够的内存,这可能会导致内存泄漏,如 MySQL bug #86821 中描述的那样。

参考链接:https://bugs.mysql.com/bug.php?id=86821结论

存储过程和触发事件在执行时被解析,即使它们从不执行“死”代码也可以也会对批处理操作的性能产生显着影响(例如,在触发器内使用时)。这意味着通过设置“标志”来禁用触发器(例如,如果 @trigger_disable =0 那么...)仍然会影响批处理操作的性能。 作者:赵玉英

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门