Mysql - 数据库查询很慢,除了索引,还有可能因为什么?
数据库查询流程
我们先来看下,一条查询语句下来,会经历哪些流程。
比如我们有一张数据库表
CREATE TABLE `user` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`name` varchar(100) NOT NULL DEFAULT '' COMMENT '名字',
`age` int(11) NOT NULL DEFAULT '0' COMMENT '年龄',
`gender` int(8) NOT NULL DEFAULT '0' COMMENT '性别',
PRIMARY KEY (`id`),
KEY `idx_age` (`age`),
KEY `idx_gender` (`gender`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
我们平常写的应用代码(go或C++之类的),这时候就叫客户端了。
客户端底层会带着账号密码,尝试向mysql建立一条TCP长链接。
mysql的连接管理模块会对这条连接进行管理。
建立连接后,客户端执行一条查询sql语句。比如:
select * from user where gender = 1 and age = 100;
客户端会将sql语句通过网络连接给mysql。
mysql收到sql语句后,会在分析器中先判断下SQL语句有没有语法错误,比如select,如果写成slect
,则会报错You have an error in your SQL syntax;
。这个报错对于我这样的手残党来说可以说是很熟悉了。
接下来是优化器,在这里会根据一定的规则选择该用什么索引。
之后,才是通过执行器去调用存储引擎的接口函数。
存储引擎类似于一个个组件,它们才是mysql真正获取一行行数据并返回数据的地方,存储引擎是可以替换更改的,既可以用不支持事务的MyISAM,也可以替换成支持事务的Innodb。这个可以在建表的时候指定。比如
CREATE TABLE `user` (
...
) ENGINE=InnoDB;
现在最常用的是InnoDB,我们就重点说这个。
InnoDB中,因为直接操作磁盘会比较慢,所以加了一层内存提提速,叫buffer pool,这里面,放了很多内存页,每一页16KB,有些内存页放的是数据库表里看到的那种一行行的数据,有些则是放的索引信息。
查询SQL到了InnoDB中。会根据前面优化器里计算得到的索引,去查询相应的索引页,如果不在buffer pool里则从磁盘里加载索引页。再通过索引页加速查询,得到数据页的具体位置。如果这些数据页不在buffer pool中,则从磁盘里加载进来。
这样就得到了想要的一行行数据,最后将得到的数据结果返回给客户端。
查询慢的可能原因
-
数据查询过慢一般是索引问题,可能是因为选错索引(索引不符合预期、走了索引还是很慢),也可能是因为查询的行数太多(分批次取,先
order by id
排序,拿取最大id
作为下次取数据的起始位置)。 -
客户端和数据库(服务端)两侧的连接数过小,会限制sql的查询并发数,增大连接数可以提升速度。
-
innodb里会有一层内存buffer pool用于提升查询速度,命中率一般>99%,如果低于这个值,可以考虑增大buffer pool的大小,这样也可以提升速度。【用于将磁盘数据页加载到内存页中,只要查询到buffer pool里有,就可以直接返回,否则就要走磁盘IO,那就慢了。也就是说,如果buffer pool 越大,那能放的数据页就越多,相应地,sql查询时就更可能命中buffer pool,那查询速度自然就更快了。】
-
server层的查询缓存(query cache)确实能为查询提速,但一般不建议打开,因为限制比较大【只适合用于那些更新极少的数据表】,并且Mysql8.0版本已经将这个功能干掉了。【按道理,如果命中缓存的话,确实是能为查询加速的。但这个功能限制很大,其中最大的问题是只要数据库表被更新过,表里面的所有缓存都会失效,数据表频繁的更新,就会带来频繁的缓存失效。】
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」