我熟练应用ctrl c和ctrl v 开发curd代码好多年了 。
MySQL查询为什么会慢,关于这个问题,在实际开发经常会遇到,而面试中,也是个高频题 。
遇到这种问题,我们一般也会想到是因为索引 。
那除开索引之外,还有哪些因素会导致数据库查询速度变慢呢?
有哪些操作,可以提升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,如果少打一个l,写成slect,则会报错You have an error in your SQL syntax; 。这个报错对于我这样的手残党来说可以说是很熟悉了 。
接下来是优化器,在这里会根据一定的规则选择该用什么索引 。
之后,才是通过执行器去调用存储引擎的接口函数 。
文章插图
Mysql架构
存储引擎类似于一个个组件,它们才是mysql真正获取一行行数据并返回数据的地方,存储引擎是可以替换更改的,既可以用不支持事务的MyISAM,也可以替换成支持事务的Innodb 。这个可以在建表的时候指定 。比如
CREATE TABLE `user` ( ...) ENGINE=InnoDB;
现在最常用的是InnoDB 。我们就重点说这个 。
InnoDB中,因为直接操作磁盘会比较慢,所以加了一层内存提提速,叫buffer pool,这里面,放了很多内存页,每一页16KB,有些内存页放的是数据库表里看到的那种一行行的数据,有些则是放的索引信息 。
文章插图
bufferPool与磁盘
查询SQL到了InnoDB中 。会根据前面优化器里计算得到的索引,去查询相应的索引页,如果不在buffer pool里则从磁盘里加载索引页 。再通过索引页加速查询,得到数据页的具体位置 。如果这些数据页不在buffer pool中,则从磁盘里加载进来 。
这样我们就得到了我们想要的一行行数据 。
文章插图
索引页与磁盘页的关系
最后将得到的数据结果返回给客户端 。
慢查询分析如果上面的流程比较慢的话,我们可以通过开启profiling看到流程慢在哪 。
mysql> set profiling=ON;Query OK, 0 rows affected, 1 warning (0.00 sec)mysql> show variables like 'profiling';+---------------+-------+| Variable_name | Value |+---------------+-------+| profiling | ON |+---------------+-------+1 row in set (0.00 sec)
然后正常执行sql语句 。这些SQL语句的执行时间都会被记录下来,此时你想查看有哪些语句被记录下来了,可以执行 show profiles;
mysql> show profiles;+----------+------------+---------------------------------------------------+| Query_ID | Duration | Query |+----------+------------+---------------------------------------------------+| 1 | 0.06811025 | select * from user where age>=60 || 2 | 0.00151375 | select * from user where gender = 2 and age = 80 || 3 | 0.00230425 | select * from user where gender = 2 and age = 60 || 4 | 0.00070400 | select * from user where gender = 2 and age = 100 || 5 | 0.07797650 | select * from user where age!=60 |+----------+------------+---------------------------------------------------+5 rows in set, 1 warning (0.00 sec)
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 学籍号怎么查询?
- Docker常用镜像安装:MySql Redis GitLab maven私服等
- 彻底解决MySQL中的乱码问题
- Linux环境下MySQL安装
- 在MySQL官网下载安装数据库
- 非常重要的mysql数据库定时备份!
- mysql5.7 使用XtraBackup2.4 全量备份还原
- Python解决滑块验证,Scarpy框架采集数据到redis数据库!
- 电信宽带怎么查询密码和帐号?
- 你的社保卡有多少钱?别还不知道,教你几招查询方法