热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

MySql优化(一)一条SQL语句的执行过程是怎样的?

写在前面:我热爱技术,热爱分享,热爱生活,我始终相信:技术是开源的,知识是共享的!

写在前面:

  • 我热爱技术,热爱分享,热爱生活, 我始终相信:技术是开源的,知识是共享的!
  • 博客里面的内容大部分均为原创,是自己日常的学习记录和总结,便于自己在后面的时间里回顾,当然也是希望可以分享自己的知识。目前的内容几乎是基础知识和技术入门,如果你觉得还可以的话不妨关注一下,我们共同进步!
  • 个人除了分享博客之外,也喜欢看书,写一点日常杂文和心情分享,如果你感兴趣,也可以关注关注!
  • 微信公众号:傲骄鹿先生




一条查询SQL是如何执行的?

程序或者工具要操作数据库, 第一步跟数据库建立连接

1、通信协议

首先, MySQL 必须要运行一个服务, 监听默认的端口(3306)。

通信协议(MySQL 支持多种通信协议。)

  • 第一个就是 TCP/IP 协议, 编程语言的连接模块都是用 TCP 协议连接到 MySQL 服务器的, 比如:mysql-connector-java-x.x.xx.jar
  • 第二种是 Unix Socket。 比如我们在 Linux 服务器, 不用通过网络协议, 也可以连接到 MySQL 的服务器, 它需要用到服务器上的一个物理文件(mysql.sock) 。
  • 另外还有命名管道( Named Pipes) 和内存共享( Share Memory) 的方式。

通信方式

MySQL 使用半双工的通信方式。半双工意味着要么是客户端向服务端发送数据, 要么是服务端向客户端发送数据, 这两个动作不能同时发生。

所以客户端发送 SQL 语句给服务端的时候, ( 在一次连接里面) 数据是不能分成小块发送的, 不管你的 SQL 语句有多大, 都是一次性发送。

如果发送给服务器的数据包过大, 我们必须要调整 MySQL 服务器配置 max_allowed_packet 参数的值( 默认是 4M) 。

另一方面, 对于服务端来说, 也是一次性发送所有的数据, 不能因为你已经取到了想要的数据就中断操作。所以, 我们一定要在程序里面避免不带 limit 的这种操作。


连接方式

MySQL 既支持短连接, 也支持长连接。 短连接就是操作完毕以后, 马上 close 掉。 长连接可以保持
打开, 后面的程序访问的时候还可以使用这个连接。
长时间不活动的连接, MySQL 服务器会断开。
show global variables like 'wait_timeout'; (非交互式超时时间, 如 JDBC 程序)

show global variables like 'interactive_timeout'; (交互式超时时间, 如 数据库工具),默认是28800s,8小时。

MySQL 默认的最大连接数是 151 个 , 最大是 16384(2^14) 。

使用 SHOW FULL PROCESSLIST;查看查询的执行状态。

一些常见的状态:

Sleep线程正在等待客户端,以向他发送一个新的语句
Query线程正在执行查询或往客户端发送数据

Locked

该查询被其他的查询锁定

Copying to tmp table on disk

临时结果集合大于tmp_table_size,线程把临时表从存储器内部格式改变为磁盘模式,以节省存储器

Sending data

线程正在为select语句处理行,同时正在向客户端发送数据

Sorting for  group

线程正在分类,以满足group by要求
Sorting for order线程正在分类,以满足oroup by要求

2、 查询缓存(Query Cache)
MySQL 内部自带了一个缓存模块。 默认是关闭的。 主要是因为 MySQL 自带的缓存的应用场景有限, 第一个是它要求 SQL 语句必须一模一样。 第二个是表里面任何一条数据发生变化的时候, 这张表所有缓存都会失效。
3、 语法解析和预处理(Parser & Preprocessor)
假如我们随便执行一个字符串或者查询一个不存在表里面的数据,会进行报错,这个就是 MySQL 的 Parser 解析器和 Preprocessor 预处理模块。

这一步主要做的事情是对 SQL 语句进行词法和语法分析和语义的解析。

词法解析
词法分析就是把一个完整的 SQL 语句打碎成一个个的单词。

比如一个简单的 SQL 语句:select name from user where id = 1;它会打碎成 8 个符号, 记录每个符号是什么类型, 从哪里开始到哪里结束。


语法解析
第二步就是语法分析, 语法分析会对 SQL 做一些语法检查,

比如单引号有没有闭合, 然后根据 MySQL定义的语法规则, 根据 SQL 语句生成一个数据结构。 这个数据结构我们把它叫做解析树。

预处理器(Preprocessor)
如果表名错误, 会在预处理器处理时报错。它会检查生成的解析树, 解决解析器无法解析的语义。 比如, 它会检查表和列名是否存在, 检查名字和别名, 保证没有歧义。


4、 查询优化(Query Optimizer) 与查询执行计划

什么是优化器?
这里存在一个问题:一条 SQL 语句是不是只有一种执行方式? 或者说数据库最终执行的 SQL 是不是就是我们发送的 SQL?
这个答案是否定的。 一条 SQL 语句是可以有很多种执行方式的。 但是如果有这么多种执行方式, 这些执行方式怎么得到的? 最终选择哪一种去执行? 根据什么判断标准去选择?
这个就是 MySQL 的查询优化器的模块(Optimizer) 。
查询优化器的目的就是根据解析树生成不同的执行计划, 然后选择一种最优的执行计划, MySQL 里面使用的是基于开销(cost) 的优化器, 那种执行计划开销最小, 就用哪种。
使用如下命令查看查询的开销:
show status like 'Last_query_cost';
如果我们想知道优化器是怎么工作的, 它生成了几种执行计划, 每种执行计划的 cost 是多少, 应该怎么做?


优化器是怎么得到执行计划的?

https://dev.mysql.com/doc/internals/en/optimizer-tracing-typical-usage.html

首先我们要启用优化器的追踪(默认是关闭的) :

启用优化器的追踪是会消耗性能的,因为他要把优化分析的结果写到表里面去,接着再执行一个sql语句,优化器会生成执行计划,这个时候优化器分析的的过程已经记录到系统表里面去了。

优化器可以做什么?
MySQL 的优化器能处理哪些优化类型呢?
比如:
1、 当我们对多张表进行关联查询的时候, 以哪个表的数据作为基准表。
2、 select * from user where a=1 and b=2 and c=3, 如果 c=3 的结果有 100 条, b=2 的结果有 200条, a=1 的结果有 300 条, 你觉得会先执行哪个过滤?
3、 如果条件里面存在一些恒等或者恒不等的等式, 是不是可以移除。
4、 查询数据, 是不是能直接从索引里面取到值。
5、 count()、 min()、 max(), 比如是不是能从索引里面直接取到值。
6、 其他。
优化器得到的结果
优化器最终会把解析树变成一个查询执行计划, 查询执行计划是一个数据结构。当然, 这个执行计划是不是一定是最优的执行计划呢? 不一定, 因为 MySQL 也有可能覆盖不到所有的执行计划。
MySQL 提供了一个执行计划的工具。 我们在 SQL 语句前面加上 EXPLAIN, 就可以看到执行计划的信息。
EXPLAIN select name from user where id=1;

5、 存储引擎(Storage Engine)

我们的数据是放在哪里的? 执行计划在哪里执行? 是谁去执行?


存储引擎基本介绍
在关系型数据库里面, 数据是放在表里面的。 我们可以把这个表理解成 Excel 电子表格的形式。所以我们的表在存储数据的同时, 还要组织数据的存储结构, 这个存储结构就是由我们的存储引擎
决定的, 所以我们也可以把存储引擎叫做表类型。在 MySQL 里面, 支持多种存储引擎, 他们是可以替换的, 所以叫做插件式的存储引擎。

为什么要搞这么多存储引擎呢? 一种还不够用吗?
是因为我们在不同的业务场景中对数据操作的要求不同, 这些不同的存储引擎通过提供不同的存储机制、 索引方式、 锁定水平等功能, 来满足我们的业务需求。


查看存储引擎

查看当前数据库所支持的存储引擎:SHOW ENGINES;


查看数据库表的存储引擎:SHOW TABLE STATUS FROM `setalone`;

在 MySQL 里面, 我们创建的每一张表都可以指定它的存储引擎, 它不是一个数据库只能使用一个存储引擎。 而且, 创建表之后还可以修改存储引擎。
数据库存放数据的路径:
show variables like 'setalone';
每个数据库有一个自己文件夹,任何一个存储引擎都有一个 frm 文件, 这个是表结构定义文件。

关于存储引擎后续再进行详细探讨。

7、 执行引擎( Query Execution Engine) , 返回结果
执行引擎, 它利用存储引擎提供了相应的 API 来完成对存储引擎的操作。 最后把数据返回给客户端, 即使没有结果也要返回。


 


推荐阅读
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文介绍了在CentOS上安装Python2.7.2的详细步骤,包括下载、解压、编译和安装等操作。同时提供了一些注意事项,以及测试安装是否成功的方法。 ... [详细]
  • 31.项目部署
    目录1一些概念1.1项目部署1.2WSGI1.3uWSGI1.4Nginx2安装环境与迁移项目2.1项目内容2.2项目配置2.2.1DEBUG2.2.2STAT ... [详细]
  • 在Oracle11g以前版本中的的DataGuard物理备用数据库,可以以只读的方式打开数据库,但此时MediaRecovery利用日志进行数据同步的过 ... [详细]
  • 本文介绍了Python对Excel文件的读取方法,包括模块的安装和使用。通过安装xlrd、xlwt、xlutils、pyExcelerator等模块,可以实现对Excel文件的读取和处理。具体的读取方法包括打开excel文件、抓取所有sheet的名称、定位到指定的表单等。本文提供了两种定位表单的方式,并给出了相应的代码示例。 ... [详细]
  • 安装mysqlclient失败解决办法
    本文介绍了在MAC系统中,使用django使用mysql数据库报错的解决办法。通过源码安装mysqlclient或将mysql_config添加到系统环境变量中,可以解决安装mysqlclient失败的问题。同时,还介绍了查看mysql安装路径和使配置文件生效的方法。 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 树莓派Linux基础(一):查看文件系统的命令行操作
    本文介绍了在树莓派上通过SSH服务使用命令行查看文件系统的操作,包括cd命令用于变更目录、pwd命令用于显示当前目录位置、ls命令用于显示文件和目录列表。详细讲解了这些命令的使用方法和注意事项。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • 本文总结了在开发中使用gulp时的一些技巧,包括如何使用gulp.dest自动创建目录、如何使用gulp.src复制具名路径的文件以及保留文件夹路径的方法等。同时介绍了使用base选项和通配符来保留文件夹路径的技巧,并提到了解决带文件夹的复制问题的方法,即使用gulp-flatten插件。 ... [详细]
  • 本文介绍了Windows操作系统的版本及其特点,包括Windows 7系统的6个版本:Starter、Home Basic、Home Premium、Professional、Enterprise、Ultimate。Windows操作系统是微软公司研发的一套操作系统,具有人机操作性优异、支持的应用软件较多、对硬件支持良好等优点。Windows 7 Starter是功能最少的版本,缺乏Aero特效功能,没有64位支持,最初设计不能同时运行三个以上应用程序。 ... [详细]
  • 如何用JNI技术调用Java接口以及提高Java性能的详解
    本文介绍了如何使用JNI技术调用Java接口,并详细解析了如何通过JNI技术提高Java的性能。同时还讨论了JNI调用Java的private方法、Java开发中使用JNI技术的情况以及使用Java的JNI技术调用C++时的运行效率问题。文章还介绍了JNIEnv类型的使用方法,包括创建Java对象、调用Java对象的方法、获取Java对象的属性等操作。 ... [详细]
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
  • 分享css中提升优先级属性!important的用法总结
    web前端|css教程css!importantweb前端-css教程本文分享css中提升优先级属性!important的用法总结微信门店展示源码,vscode如何管理站点,ubu ... [详细]
author-avatar
壹舊雲A
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有