一、什么是慢SQL

慢SQL是指那些执行效率低下、响应时间长,导致用户等待时间变长和服务器资源利用率下降的SQL查询。那么,如何定义一个SQL查询是"慢"的呢?这不是一个绝对时间的问题,而是需要从多维度考量。

时间维度

最常见的定义慢SQL的方法是时间阈值。这个阈值可以根据不同的系统和性能要求设置。例如,一个查询如果在网页应用中执行时间超过2秒,或在数据分析系统中执行超过30秒,就可以被认为是慢的。

业务场景维度

单纯的时间阈值并不足以定义所有场景下的慢SQL。在不同的业务场景下,对性能的要求也不同。例如,对于在线交易系统,即便是几百毫秒的延迟也可能导致用户体验下降和收入损失,而对于后台数据分析任务,稍长的执行时间可能是可接受的。另外,出于一些历史原因有的SQL查询可能非常复杂,需要同时关联非常多的表,使用一些复杂的函数、子查询,这样的SQL在项目初期由于业务数据量比较少,不会对数据库造成较大的压力,但是随着时间的积累以及业务的发展,这些SQL慢慢就会转变为慢SQL,对数据库的性能产生一定的影响。

资源使用维度

除了执行时间,SQL语句对系统资源的使用也是衡量其是否"慢"的一个重要维度。如果一个SQL查询导致了大量的CPU或内存消耗,甚至影响了其他查询的性能,那么它也可以被视为慢SQL。

频率和影响维度

有些SQL查询可能本身执行时间不长,但它们被频繁调用,累积起来对系统性能产生重大影响。另外,SQL执行的时间可能在系统空闲时无关紧要,但在高峰期可能会成为瓶颈。

用户体验维度

用户的感受也是定义慢SQL的一个重要维度。如果查询延迟导致用户界面卡顿,影响了用户的操作流程,即使查询本身不算太慢,用户体验也会告诉我们它是“慢”的。

因此,慢SQL的定义是多维度的,它需要从执行时间、业务场景、资源消耗、频率及影响以及用户体验等多方面的考量。

二、慢SQL产生原因

产生慢SQL的原因有很多,以下只是列出常见原因。

1.硬件问题

如果数据库本身的性能压力比较大,资源比较紧张,CPU占用率或者IO利用率很高,这时会导致所有的语句执行起来都比较慢。当然压力大的原因又有很多种,比如服务器参数设置(my.cnf)、磁盘空间满、内存不足、网速问题等等。

2.无索引、索引失效导致

表的数据量越大,如果SQL又没有走索引,很容易发生查询慢的问题。所以对于大数据量的查询,需要建立适合的索引来优化查询。虽然我们很多时候建立了索引,但在一些特定的场景下,索引还有可能会失效,所以索引失效也是导致慢查询的主要原因之一。

3.锁等待

执行SQL的时候,如遇到表锁或者行锁,只能等待锁被释放,就会导致慢SQL。

4.不恰当的 SQL 语句

使用不恰当的 SQL 语句也是慢 SQL 最常见的诱因之一 :在大数据表中使用分页查询、多表join查询,以及对非索引字段进行排序等等。

三、慢SQL危害

1. 资源占用增加,影响其他请求响应时间

每个SQL执行都需要消耗一定的I/O资源,SQL执行的快慢,决定资源被占用时间的长短。假设总资源是10,有一条慢SQL占用了3的资源共计1分钟。那么在这1分钟时间内,其他SQL能够分配的资源总量就是7,如此循环,当资源分配完的时候,所有新的SQL执行将会排队等待。

2. 拖垮系统,引发故障

慢SQL占用数据库连接的时间长,如果有大量慢SQL查询同时执行,可能会导致数据库连接池的连接被全部占用,并导致数据连接池打满、缓冲区溢出等问题,使数据库无法响应其他请求,同时占用mysql大量内存,严重时会导致服务器直接挂掉,整个系统直接瘫痪。

3. 数据不一致问题

慢SQL造成数据库幻读、不可重复读的概率更大,假设该慢SQL是一个更新操作但因执行时间过长未提交,而另一条SQL也在更新数据并且已提交,用户再次查询的时候,看到的数据可能与实际结果不符。此外慢SQL的执行时间过长,可能会导致应用的进程因超时被kill,无法返回结果到客户端。

4. 影响用户体验

SQL的执行时间越长,系统的响应时间延迟,就会导致用户操作界面卡顿,影响用户体验。

四、从管控角度谈慢SQL优化

关于慢SQL的优化网上已经有大量资料可以参考,这里不再阐述,下面从管控角度谈如何对慢SQL进行整治。作为横向的风险隐患治理团队,为了对公司内部多个部门多个系统进行慢SQL治理,我们总结了几点经验,仅供参考。

1.善用工具发现慢SQL

目前发现慢SQL的工具有很多,很多企业也打造了自己的定制化慢SQL工具,当然像Mysql也有自己的慢查询日志功能可以用来分析慢SQL,不过功能比较粗糙,慢查询日志杂乱无序,无法反映系统当前状况以及SQL对系统的影响,不方便长期跟踪治理。而通过慢SQL分析平台,对系统中的慢SQL进行统计、分析、分组,能够准确反映每个慢SQL对系统的影响,实时展示当前系统数据库的慢SQL情况,并可以对慢SQL风险进行数字化打分,方便我们对慢SQL分级治理。

2.慢SQL告警

由于慢SQL原因的复杂性和多样性,出现一条慢SQL就发告警显然是不合理,且很多时候慢SQL是结果而非原因,我们的做法是监控每五分钟的慢查询数量环比增长情况,各系统根据实际情况自行设置不同的阈值,此外要求各系统每次发版之后重点检查慢SQL新增情况。

3.分级治理、长期追踪

慢SQL治理是一个需要长期坚持做的事情,我们的做法是每月取数据库主机cpu使用率TOP10数据库清单,拉出top清单中的TOP5慢SQL(根据评分排序),并组织相关系统进行优化,对比优化前后的负载情况,形成成效,最终实现解决慢查询从“被动”到“主动”的完美转换。