MySQL常见问题之SQL查询慢

面对SQL查询慢的问题,首先区分是偶尔还是一直慢。偶尔慢可能涉及数据库锁、刷新脏页、备份任务等因素;一直慢则重点检查SQL本身。关注数据量、不必要的数据请求、索引使用、关联查询和子查询、索引创建合理性及类型转换影响。通过explain分析执行计划,优化SQL,必要时调整业务逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

可能是经常处理业务,最近总是听到开发的同学说SQL的查询慢。然后问我为什么,让我在数据库层面找原因。这样的需求接的多了,对于这类需求,我已经有了一套比较官方的回答思路,我来说,大家看,看看还有什么没有考虑到的地方,欢迎指正。
首先,当有业务方对我说SQL查询慢的时候,一般我会先问几个问题:
1、这个SQL是偶尔比较慢还是一直这么慢?
如果是偶尔比较慢,那大概率说明不是SQL层面的问题,应该是在某个时间点遇到了数据库的其他动作,导致产生了影响,例如:
第一、该条语句要扫描的表被加锁了,所以导致拿不到数据,查询很慢。
第二、查询的时间点,恰好数据库在刷新脏页,我们知道数据库进行了更新操作之后,不会立刻将这些数据进行落盘,而是刷新到redo log中去,等到空闲的时候,通过redo log里面的日志将数据同步到磁盘中去。
第三、当前时间点正在进行一个大的备份任务,导致磁盘的IO突然增高,内存和磁盘的交互速度变慢,自然而然,查询的速度也就降下来了。
第四、其他未知的神秘力量,例如大表操作、大事务、网络带宽被占用等等

如果是一直这么慢,一般情况下,SQL层面的问题可能比较大,而SQL层面,首先要考虑这几个要素:
1、表的数据量有多大?上亿条还是只有几万条?如果是上亿条,那还说得过去,如果是几万条但是速度很慢,大概率是SQL质量太差。
2、是否向数据库请求了不必要的数据,例如只需要100条数据,但是却扫描了全表。也就是扫描行数和返回的行数相差太多,这个时候需要重新写SQL,避免不必要的数据访问。
3、表中的字段是否拥有索引?SQL是否使用到了索引?这种情况下,我们可以使用explain的方法查看该SQL的执行计划,然后查看执行计划中的rows列和type列,其中rows列反映的是扫描的行数,而type列反映的是扫描该表的方法。如果表没有建立索引,应该根据SQL的具体内容,为表创建相关的索引。
4、SQL中是否使用了很多的关联查询和子查询,例如SQL中包含很多个left join或者对于一个大的结果集进行group by操作。
5、如果表使用到了索引,就要看看索引创建的合理性了,是否在一些基数比较小的字段上创建了索引,导致索引的作用没有发挥出来,还导致"回表"操作,引发性能损耗,此时,修改表的索引就变得很必要了。
6、比较隐蔽的一个问题,就是字段上如果进行了数据的类型转换或者函数操作,那么这个SQL是用不到该字段的索引的,这个问题很早之前遇到过几次,当时也是迟迟查不出来原因,例如
select xxx from tbl where a*2 < 4

select xxx from tbl where a<2
是不一样的,如果在a列上指定了索引,那么前者不会用到索引,而后者才能用到索引。
分析完这些,如果性能还是比较差,那就应该针对SQL进行优化了,通过explain查看当前的查询类型,针对SQL进行重写。如果重新之后还是不行,那可能就得从业务层面进行调整了,不过一般不用走到这一步,SQL的问题都能够解决。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值