MySQL 执行一条 select 语句,期间发生了什么?

参考网址
https://www.xiaolincoding.com/mysql/base/how_select.html
本文记录下基于 SQL 查询流程,可能导致查询速度慢的情况(自己总结,细节部分 chatGPT ,错误欢迎指正)
网络原因
连接 mysql 服务使用 tcp ,三次握手避免不了,四次挥手的时间取决于是短链接还是长连接
由于 MySQL 在执行查询过程中临时使用内存管理连接对象,如果长连接累计很多,将导致 MySQL 服务占用内存太大,可能会导致系统变慢,甚至会被系统强制杀掉,可定期断开长连接或者客户端主动重置连接(使用函数 mysql_reset_connection())查询缓存
字面意思,以sql查询语句为键,sql查询语句的结果为值,若是缓存有则直接返回,无需查表来提升查询速度。
所以写sql时尽量将长sql拆分成多个短sql,便于命中缓存。
但是对于更新比较频繁的表,查询缓存的命中率很低,因为只要一个表有更新操作,那么这个表的查询缓存就会被清空。若刚缓存了个查询结果很大的数据且没被使用的时候,刚好这个表有更新操作,查询缓冲就被清空了,相当于缓存了个寂寞
所以MySQL 8.0 版本直接将查询缓存删掉了,也就是说 MySQL 8.0 开始,执行一条 SQL 查询语句,不会再走到查询缓存这个阶段了。
所以查询缓存MySQL8.0版本之前可使用,且最好时查询功能较多的系统来进行使用索引
- 未使用索引
就是未使用索引,导致全表查询 - 索引失效
- 隐式转化(常见于使用订单号查询订单,直接一串数字,不会使用索引)
列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引
据类型出现隐式转化。如varchar不加单引号的话可能会自动转换为int型,使索引无效,产生全表扫描
隐式转换name = ‘111’ 会使用到 name = 111 不会使用到
因为当name值为111a 111q 111sxzcs都会跟111匹配 - 不符合索引最左前缀原则
对于复合索引,只有在查询的条件满足索引的最左前缀时,索引才能被充分利用。如果查询条件不符合最左前缀原则,那么索引可能无法有效使用,导致索引失效。 - 使用函数或表达式
查询中使用了函数或表达式对索引列进行了处理,那么索引可能无法被有效利用。例如,WHERE DATE_FORMAT(date_column, ‘%Y-%m’) = ‘2023-12’,这种情况下,即使 date_column 上存在索引,也无法被利用
还有常用的 like 语句,若是时%开头,也会索引失效 - 数据分布不均匀(这个我认为是创建表时的问题,重复率太高就不该有索引)
索引列上的数据分布不均匀,例如某些值出现的频率过高或过低,那么索引可能无法提供良好的性能,甚至导致索引失效 - 数据量过大
对于某些大型表,索引可能无法完全载入内存,这样在执行查询时会导致频繁的磁盘 I/O 操作,影响查询性能 - 使用 NOT、OR 等条件(这个我不熟,贴个图片,免得以后再看忘了)
- 隐式转化(常见于使用订单号查询订单,直接一串数字,不会使用索引)
- 未使用索引
比较好玩的问答
- 同一条sql,同一个数据库,早上查询很快,下午很慢,为什么
- 数据库服务器负载(可回答),网络问题(可回答),查询缓存(可回答),索引失效(可回答,为什么会失效?这点非常好玩,因为从上午到下午,表里面可能插入了大量数据,导致数据分布不均匀还有数据量过大,参考第三点)