很多时候所谓的的查询优化工作实际上就是遵循一些原则让MySQL的优化器能够按照预想的合理方式运行而已。

MySQL的逻辑架构图如下所示

MySQL逻辑架构整体分为三层。其中最上层为客户端层,并非MySQL所独有,诸如:连接处理、授权认证、安全等功能均在这一层处理。

中间这一层包含大多数MySQL核心服务,包括查询、解析、分析、优化、缓存、内置函数(比如:时间、数学、加密等函数)。所有的跨存储引擎的功能也在这一层实现:存储过程、触发器、视图等。

最下层为存储引擎,其负责MySQL中的数据存储和提取。和Linux下的文件系统类似,每种存储引擎都有其优势和劣势。中间的服务层通过API与存储引擎通信,这些API接口屏蔽了不同存储引擎间的差异。

MySQL查询过程

MySQL整个查询执行过程,总的来说分为6个步骤客户端向MySQL服务器发送一条查询请求

服务器首先检查查询缓存,如果命中缓存,则立刻返回存储在缓存中的结果。否则进入下一阶段

服务器进行SQL解析、预处理

由优化器生成对应的执行计划

MySQL根据执行计划,调用存储引擎的API来执行查询

将结果返回给客户端,同时缓存查询结果

上述过程如下图所示:

客户端/服务端通信协议

MySQL客户端/服务端通信协议是“半双工”的:在任一时刻,要么是服务器向客户端发送数据,要么是客户端向服务器发送数据,这两个动作不能同时发生。一旦一端开始发送消息,另一端要接收完整个消息才能响应它,所以我们无法也无须将一个消息切成小块独立发送,也没有办法进行流量控制。

客户端用一个单独的数据包将查询请求发送给服务器,所以当查询语句很长的时候,需要设置max_allowed_packet参数。但是需要注意的是,如果查询实在是太大,服务端会拒绝接收更多数据并抛出异常。

与之相反的是,服务器响应给用户的数据通常会很多,由多个数据包组成。但是当服务器响应客户端请求时,客户端必须完整的接收整个返回结果,而不能简单的只取前面几条结果,然后让服务器停止发送。因而在实际开发中,尽量保持查询简单且只返回必需的数据,减小通信间数据包的大小和数量是一个非常好的习惯,这也是查询中尽量避免使用SELECT *以及加上LIMIT限制的原因之一。

查询缓存

MySQL查询缓存的过程如下图所示:

缓存命中率可以通过如下公式计算:Qcache_hits/(Qcache_hits + Com_select)来计算。

在解析一个查询语句前,如果查询缓存是打开的,那么MySQL会检查这个查询语句是否命中查询缓存中的数据。如果当前查询恰好命中查询缓存,在检查一次用户权限后直接返回缓存中的结果。这种情况下,查询不会被解析,也不会生成执行计划,更不会执行。

MySQL将缓存存放在一个引用表(不要理解成table,可以认为是类似于HashMap的数据结构),通过一个哈希值索引,这个哈希值通过查询本身、当前要查询的数据库、客户端协议版本号等一些可能影响结果的信息计算得来。所以两个查询在任何字符上的不同(例如:空格、注释),都会导致缓存不会命中。

如果查询中包含任何用户自定义函数、存储函数、用户变量、临时表、mysql库中的系统表,其查询结果都不会被缓存。比如函数NOW()或者CURRENT_DATE()会因为不同的查询时间,返回不同的查询结果,再比如包含CURRENT_USER或者CONNECION_ID()的查询语句会因为不同的用户而返回不同的结果,将这样的查询结果缓存起来没有任何的意义。

然是缓存,就会失效,那查询缓存何时失效呢?MySQL的查询缓存系统会跟踪查询中涉及的每个表,如果这些表(数据或结构)发生变化,那么和这张表相关的所有缓存数据都将失效。正因为如此,在任何的写操作时,MySQL必须将对应表的所有缓存都设置为失效。如果查询缓存非常大或者碎片很多,这个操作就可能带来很大的系统消耗,甚至导致系统僵死一会儿。而且查询缓存对系统的额外消耗也不仅仅在写操作,读操作也不例外:任何的查询语句在开始之前都必须经过检查,即使这条SQL语句永远不会命中缓存

如果查询结果可以被缓存,那么执行完成后,会将结果存入缓存,也会带来额外的系统消耗

最后的忠告是不要轻易打开查询缓存,特别是写密集型应用。

如果你实在是忍不住,可以将query_cache_type设置为DEMAND,这时只有加入SQL_CACHE的查询才会走缓存,其他查询则不会,这样可以非常自由地控制哪些查询需要被缓存。

常见的查询缓存的配置如下所示query_cache_type:是否打开查询缓存。可以设置为OFF、ON和DEMAND。DEMAND表示只有在查询语句中明确写明SQL_CACHE的语句才会放入查询缓存。

query_cache_size:查询缓存使用的总内存空间。

query_cache_min_res_unit:在查询缓存中分配内存块时的最小单元。较小的该值可以减少碎片导致的内存空间浪费,但是会导致更频繁的内存块操作。

query_cache_limit:MySQL能够查询的最大查询结果。如果查询结果大于这个值,则不会被缓存。因为查询缓存在数据生成的时候就开始尝试缓存数据,所以当结果全部返回后,MySQL才知道查询结果是否超出限制。超出之后,才会将结果从查询缓存中删除。

语法解析和预处理

MySQL通过关键字将SQL语句进行解析,并生成一颗对应的解析树。这个过程解析器主要通过语法规则来验证和解析。比如SQL中是否使用了错误的关键字或者关键字的顺序是否正确等等。预处理则会根据MySQL规则进一步检查解析树是否合法。比如检查要查询的数据表和数据列是否存在等等。

查询优化

经过前面的步骤生成的语法树被认为是合法的了,并且由优化器将其转化成查询计划。多数情况下,一条查询可以有很多种执行方式,最后都返回相应的结果。优化器的作用就是找到这其中最好的执行计划。

MySQL使用基于成本的优化器,它尝试预测一个查询使用某种执行计划时的成本,并选择其中成本最小的一个。在MySQL可以通过查询当前会话的last_query_cost的值来得到其计算当前查询的成本。

查询执行引擎

在完成解析和优化阶段以后,MySQL会生成对应的执行计划,查询执行引擎根据执行计划给出的指令逐步执行得出结果。整个执行过程的大部分操作均是通过调用存储引擎实现的接口来完成,这些接口被称为handler API。查询过程中的每一张表由一个handler实例表示。实际上,MySQL在查询优化阶段就为每一张表创建了一个handler实例,优化器可以根据这些实例的接口来获取表的相关信息,包括表的所有列名、索引统计信息等。存储引擎接口提供了非常丰富的功能,但其底层仅有几十个接口,这些接口像搭积木一样完成了一次查询的大部分操作。

返回结果给客户端

查询执行的最后一个阶段就是将结果返回给客户端。即使查询不到数据,MySQL仍然会返回这个查询的相关信息,比如该查询影响到的行数以及执行时间等等。

如果查询缓存被打开且这个查询可以被缓存,MySQL也会将结果存放到缓存中。

结果集返回客户端是一个增量且逐步返回的过程。有可能MySQL在生成第一条结果时,就开始向客户端逐步返回结果集了。这样服务端就无须存储太多结果而消耗过多内存,也可以让客户端第一时间获得返回结果。需要注意的是,结果集中的每一行都会以一个满足①中所描述的通信协议的数据包发送,再通过TCP协议进行传输,在传输过程中,可能对MySQL的数据包进行缓存然后批量发送。

mysql 数据库生命周期_MySQL生命周期相关推荐

  1. mysql数据库物理结构设计_MySQL数据库结构设计

    前言 在编码过程中,如果MySQL数据结构设计不好的话,会大大影响开发人员编码效率.比如说MySQL数据库表设计不规范,创建时间字段设计成cjsj,创建者字段设计成cjr或者cjz.这样的数据库表可读 ...

  2. mysql 数据库名称限制_mysql 数据库名称限制

    mysql 数据库名称限制 云服务器(Elastic Compute Service,简称ECS)是阿里云提供的性能卓越.稳定可靠.弹性扩展的IaaS(Infrastructure as a Serv ...

  3. mysql数据库咋还原_mysql数据库备份和还原

    一.数据备份 1.使用mysqldump命令备份 mysqldump命令将数据库中的数据备份成一个文本文件.表的结构和表中的数据将存储在生成的文本文件中. mysqldump命令的工作原理很简单.它先 ...

  4. mysql数据库 博客_mysql数据库教程--第 页-杨雨个人博客-关注互联网和搜索引擎的技术博客...

    发布时间:19-07-02 作者:杨雨 分类:mysql教程 Mysql主从基本原理,主要形式以及主从同步延迟原理 (读写分离)导致主库从库数据不一致问题的及解决方案.从数据库(Slave)是主数据库 ...

  5. mysql数据库备份方案_MySQL平台数据库备份方案详细说明

    在数据库表丢失或损坏的情况下,备份你的数据库是很重要的.如果发生系统崩溃,你肯定想能够将你的表尽可能丢失最少的数据恢复到崩溃发生时的状态.有时,正是MySQL管理员造成破坏.管理员已经知道表已破坏,用 ...

  6. mysql数据库优化命令_MySQL数据库优化总结

    一个:MySQL标准数据库优化注意事项 1.数据库设计(表设计合理)三范式(规范的模式) 三范式包含: 第一范式:1NF是对属性的原子性的约束.要求属性具有原子性,不可再分解.(仅仅要是关系型数据库都 ...

  7. mysql 数据库 数组类型转换_mysql数字类型的数据如何进行转换?

    如何将MySQL数据库中的数字类型转换为数字函数,今天给大家介绍mysql中的转换函数,这个在实际的生活应用中是运用广泛的,大大减少了我们自己手动进行数字类型的转换. 我们今天主要向大家介绍的是用My ...

  8. mysql数据库备份总结_mysql中mysqlhotcopy备份数据库总结

    mysqlhotcopy是mysql数据库中一个备份工具,相对于mysqldump是一个快速文件意义上的COPY,mysqlhotcopy是一个数据库端的SQL语句集合. mysqlhotcopy用法 ...

  9. mysql数据库查询缓存_MySQL查询缓存与数据库管理

    MySQL查询缓存与数据库管理 上一篇 / 下一篇  2010-01-25 21:51:07 / 个人分类:MYSQL/Cache MySQL查询缓存 注意:查询缓存绝不返回过期数据. 如果一个表发生 ...

  10. mysql 数据库异常大_Mysql连接数据库异常汇总【必收藏】

    在Centos上部署项目发现一个奇怪的问题,数据库连接一直抛异常.于是花了两个小时搜了各种数据库连接异常导致的原因,最终问题得以解决.同时,把解决过程中搜集到的异常信息汇总一下,当大家遇到类似的问题时 ...

最新文章

  1. 剖析IntentService的运作机理
  2. Python学习笔记--程序控制结构
  3. Unity3D Input按键系统
  4. LocalReport Print with C# C#打印RDLC
  5. Document builder customizing
  6. 【操作系统】 第二章 进程的描述与控制
  7. play for scala 通过网易smtp发送邮件
  8. CentOS系统性能工具 sar 示例!
  9. nyoj 19 擅长排列的小明(深搜,next_permutation)
  10. TransE算法(Translating Embedding)
  11. vue中echarts迁徙图
  12. e次方用计算机怎么算百分比,e指数计算器
  13. Android获取缓存大小和清除缓存功能实现
  14. docker的代理配置_wuli大世界_新浪博客
  15. [Excel]vlookup的内在逻辑以及模糊检索
  16. 《禅与摩托车维修艺术》
  17. 文件服务器之一:NFS 服务器
  18. 工作十年的数据分析师被炒,没有方向,你根本躲不过中年危机
  19. 【Java】Log4j日志
  20. 【物联网】第2章 自动识别技术与RFID

热门文章

  1. 【历史上的今天】8 月 6 日:拯救了苹果的微软投资;万维网首次公开亮相;AWK 作者出生
  2. python键盘按键名称_跑Python的键盘可以很强大
  3. 分布式事务数据库HotDBV2.5.4版本
  4. 破梦幻老是显示服务器繁忙,为什么今天进梦幻老是提示服务器繁忙或者网络繁忙!...
  5. python程序设计题答案_Python程序设计课后习题答案
  6. Python技能树丨Python简介
  7. RGB与YUV颜色空间
  8. BZOJ1816(二分)
  9. 真空镀膜玻璃基透明电路板
  10. [Leetcode每日一题] 819. 最常见的单词