mysql体系结构简单概述:

  1. Connectors:接入方,支持协议很多
  2. Management Serveices & Utilities:系统管理和控制工具例如:备份恢复,mysql复制集群等
  3. Connection Pool:连接池:管理缓冲用户连接、用户名、密码、权限校验、线程处理等需要缓存的需求
  4. SQL Interface:SQL接口:接受用户的SQL命令,并且返回用户需要查询的结果。比如select from就是调用SQL Interface
  5. Parser: 解析器,SQL命令传递到解析器的时候会被解析器验证和解析。解析器是由Lex和YACC实现的。
  6. Optimizer: 查询优化器,SQL语句在查询之前会使用查询优化器对查询进行优化
  7. Cache和Buffer(高速缓存区): 查询缓存,如果查询缓存有命中的查询结果,查询语句就可以直接去查询缓存中取数据。
  8. pluggable storage Engines:插件式存储引擎。存储引擎是MySql中具体的与文件打交道的子系统。也是Mysql最具有特色的一个地方。 Mysql的存储引擎是插件式的。
  9. file system  :文件系统,数据、日志(redo,undo)、索引、错误日志、查询记录、慢查询等

常见的存储引擎:

Mysql插拔式的存储引擎:

  1. 插拔式的插件方式。
  2. 存储引擎是指定在表之上的,即一个库中的每一个表都可以指定专用的存储引擎。
  3. 不管表采用什么样的存储引擎,都会在数据区,产生对应的一个frm文件(表结构定义描述文件)。

CSV:https://dev.mysql.com/doc/refman/5.7/en/csv-storage-engine.html

  数据存储以CSV文件,会生成3个文件 table_name.CSM(元数据状态管理,数据行) table_name.CSV(数据文件) table_name.frm。特点:

  不能定义没有索引、列定义必须为NOT NULL。

  不能设置自增列,不适用大表或者数据的在线处理。

  CSV数据的存储用,隔开,可直接编辑CSV文件进行数据的编排,数据安全性低。

注:编辑之后,要生效使用 flush table XXX 命令。

应用场景:数据的快速导出导入,表格直接转换成CSV。

Archive:https://dev.mysql.com/doc/refman/5.7/en/archive-storage-engine.html

  会生成 table_name.ARZ   table_name.frm,数据存储为ARZ文件格式。特点:

  只支持 insert 和 select 两种操作,只允许自增ID列建立索引,行级锁,不支持事务,数据占用磁盘少。

应用场景:日志系统,大量的设备数据采集。

Memory(heap):https://dev.mysql.com/doc/refman/5.7/en/memory-storage-engine.html

  数据都是存储在内存中,IO效率要比其他引擎高很多,服务重启数据丢失,内存数据表默认只有16M。特点:

  支持hash索引,B tree索引,默认hash(查找复杂度0(1)),字段长度都是固定长度varchar(32)=char(32),不支持大数据存储类型字段如 blog,text,表级锁

应用场景:等值查找热度较高数据,查询结果内存中的计算,大多数都是采用这种存储引擎,作为临时表存储需计算的数据。

Myisam:https://dev.mysql.com/doc/refman/5.7/en/myisam-storage-engine.html

  Mysql5.5版本之前的默认存储引擎,较多的系统表也还是使用这个存储引擎,系统临时表也会用到Myisam存储引擎。特点:

  select count(*) from table 无需进行数据的扫描,数据(MYD)和索引(MYI)分开存储,表级锁,不支持事务。

Innodb:https://dev.mysql.com/doc/refman/5.7/en/innodb-introduction.html

  在创建好表结构并且指定搜索引擎为 Myisam之后,会在数据目录生成3个文件,分别是table_name.frm(表结构文件),table_name.idb(数据与索引保存文件)。Mysql5.5及以后版本的默认存储引擎

  Key Advantages:Its DML operations follow the ACID model [事务ACID]。

  Row-level locking[行级锁]InnoDB tables arrange your data on disk to optimize queriesbased on primary keys[聚集索引(主键索引)方式进行数据存储]。

  To maintain data integrity, InnoDB supports FOREIGN KEY constraints[支持外键关系保证数据完整性]。

  接下来看一下这些常用的搜索引擎的简单对比图,也能看出为什么InnoDB最后悔脱颖而出:

MySQL运行机理:

  由下图可以看出Mysql的执行流程大致分为 5 个阶段:

  1. mysql 客户端/服务端通信阶段。
  2. 查询缓存阶段。
  3. 查询优化处理阶段。
  4. 查询执行引擎阶段。
  5. 返回客户端阶段。

  我们可以根据执行的流程来看一下在优化的过程中需要注意点什么。

1.mysql 客户端/服务端通信阶段:

Mysql客户端与服务端的通信方式是“半双工”的通信方式,通信方式主要分为以下三种:

  • 全双工:双向通信,发送同时也可以接收
  • 半双工:双向通信,同时只能接收或者是发送,无法同时做操作
  • 单工:只能单一方向传送

半双工通信:

  在任何一个时刻,要么是有服务器向客户端发送数据,要么是客户端向服务端发送数据,这两个动作不能同时发生。所以我们无法也无需将一个消息切成小块进行传输

特点和限制:

  客户端一旦开始发送消息,另一端要接收完整个消息才能响应。客户端一旦开始接收数据没法停下来发送指令。

mysql 客户端/服务端通信--查询状态

  有一整套状态集去管理状态。对于一个mysql连接,或者说一个线程,时刻都有一个状态来标识这个连接正在做什么。查看命令 show full processlist / show processlist

  

  要了解状态的全过程请登录:https://dev.mysql.com/doc/refman/5.7/en/general-thread-states.html (状态全集)。以下是常见的状态集:

  • Sleep:线程正在等待客户端发送数据
  • Query:连接线程正在执行查询
  • Locked:线程正在等待表锁的释放
  • Sorting result:线程正在对结果进行排序
  • Sending data:向请求端返回数据

  异常情况下可通过kill {id}的方式进行连接的杀掉

2.查询缓存阶段:

  工作原理:缓存SELECT操作的结果集和SQL语句;新的SELECT语句,先去查询缓存,判断是否存在可用的记录集。

  判断标准:与缓存的SQL语句,是否完全一样,区分大小写 (简单认为存储了一个key-value结构,key为sql,value为sql查询结果集)。

  可以通过以下命令来查看缓存的设置情况:

在my.cnf配置文件中可以配置:

query_cache_type:

  • 值:0 -– 不启用查询缓存,默认值;
  • 值:1 -– 启用查询缓存,只要符合查询缓存的要求,客户端的查询语句和记录集都可以缓存起来,供其他客户端使用,加上 SQL_NO_CACHE将不缓存 ,如select SQL_NO_CACHE *from.......
  • 值:2 -– 启用查询缓存,只要查询语句中添加了参数:SQL_CACHE,且符合查询缓存的要求,客户端的查询语句和记录集,则可以缓存起来,供其他客户端使用

query_cache_size:允许设置query_cache_size的值最小为40K,默认1M,推荐设置 为:64M/128M;

query_cache_limit:限制查询缓存区最大能缓存的查询记录集,默认设置为1M

  可以通过 show status like 'Qcache%' 命令可查看缓存情况:

  需要注意的是,一旦表数据发生一点变化,与这个表所相关的缓存全部失效,不会缓存的情况:

  1. 当查询语句中有一些不确定的数据时,则不会被缓存。如包含函数NOW(),SQL_NO_CACHE,CURRENT_DATE()等类似的函数,或者用户自定义的函数,存储函数,用户变量等都不会被缓存。
  2. 当查询的结果大于query_cache_limit设置的值时,结果不会被缓存。
  3. 对于InnoDB引擎来说,当一个语句在事务中修改了某个表,那么在这个事务提交之前,所有与这个表相关的查询都无法被缓存。因此长时间执行事务,会大大降低缓存命中率。
  4. 查询的表是系统表。
  5. 查询语句不涉及到表。

为什么mysql默认关闭了缓存开启??

  1. 在查询之前必须先检查是否命中缓存,浪费计算资源。
  2. 如果这个查询可以被缓存,那么执行完成后,MySQL发现查询缓存中没有这个查询,则会将结果存入查询缓存,这会带来额外的系统消耗。
  3. 针对表进行写入或更新数据时,将对应表的所有缓存都设置失效。
  4. 如果查询缓存很大或者碎片很多时,这个操作可能带来很大的系统消耗。

适用场景 :以读为主的业务,数据生成之后就不常改变的业务。比如门户类、新闻类、报表类、论坛类等

3.查询优化处理阶段:

  查询优化处理的三个阶段:

  • 解析sql:通过lex词法分析,yacc语法分析将sql语句解析成解析树 https://www.ibm.com/developerworks/cn/linux/sdk/lex/。
  • 预处理阶段:根据mysql的语法的规则进一步检查解析树的合法性,如:检查数据的表和列是否存在,解析名字和别名的设置。还会进行权限的验证。
  • 查询优化器:优化器的主要作用就是找到最优的执行计划。

  查询优化器如何找到最优计划 ,通过explain  +查询sql查看执行计划+\G。

  查询优化器如何找到最优执行计划,有如下规则:

  1. 使用等价变化规则:5 = 5 and a > 5 改写成 a > 5,a < b and a = 5 改写成 b > 5 and a = 5
  2. 基于联合索引,调整条件位置等
  3. 优化count 、min、max等函数:min函数只需找索引最左边,max函数只需找索引最右边,myisam引擎count(*)
  4. 覆盖索引扫描:如果是建立了一个 name 字段的索引,InnoDB由于叶子节点保存了ID索引的key值,这种情况下 使用 select id,name from。。。这个也会用到覆盖索引
  5. 子查询优化  
  6. 提前终止查询:用了limit关键字或者使用不存在的条件,选择不同的索引来执行,在采用limit的情况下,查询优化器在成本计算的过程中也可以选择离散型不高的列索引。
  7. IN的优化:用 or的情况是一条一条去比对,in:用二分法,where in(1,2,3,4,5),先排序条件后再比对中间位置 3,通过二分查找法进行查找,当条件多的情况下  ,相对来说的话in的优化会好一点。先进性排序,再采用二分查找的方式

  Mysql的查询优化器是基于成本计算的原则。他会尝试各种执行计划。数据抽样的方式进行试验(随机的读取一个4K的数据块进行分析)。

  mysql查询优化 -执行计划:使用命令查看一句查询SQL,看看查询计划中都涉及什么有用的信息

id:select查询的序列号,标识执行的顺序

  • id相同,执行顺序由上至下,联表查询使用union  id为空。
  • id不同,如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行
  • id相同又不同即两种情况同时存在,id如果相同,可以认为是一组,从上往下顺序执行;在所有组中,id值越大,优先级越高,越先执行

select_type:查询的类型,主要是用于区分普通查询、联合查询、子查询等

  • SIMPLE:简单的select查询,查询中不包含子查询或者union
  • PRIMARY:查询中包含子部分,最外层查询则被标记为primary
  • SUBQUERY/MATERIALIZED:SUBQUERY表示在select 或 where列表中包含了子查询
  • MATERIALIZED表示where 后面in条件的子查询
  • UNION:若第二个select出现在union之后,则被标记为union;
  • UNION RESULT:从union表获取结果的select

table :查询涉及到的表

  • 直接显示表名或者表的别名
  • <unionM,N> 由ID为M,N 查询union产生的结果
  • <subqueryN> 由ID为N查询生产的结果

type:访问类型,sql查询优化中一个很重要的指标,结果值从好到坏依次是:system > const > eq_ref > ref > range > index > ALL

  • system:表只有一行记录(等于系统表),const类型的特例,基本不会出现,可以忽略不计
  • const:表示通过索引一次就找到了,const用于比较primary key 或者 unique索引
  • eq_ref:唯一索引扫描,对于每个索引键,表中只有一条记录与之匹配。常见于主键 或 唯一索引扫描
  • ref:非唯一性索引扫描,返回匹配某个单独值的所有行,本质是也是一种索引访问
  • range:只检索给定范围的行,使用一个索引来选择行(至少要这个级别)
  • index:Full Index Scan,索引全表扫描,把索引从头到尾扫一遍
  • ALL:Full Table Scan,遍历全表以找到匹配的行

执行计划:

possible_keys:查询过程中有可能用到的索引

key:实际使用的索引,如果为NULL,则没有使用索引 rows,根据表统计信息或者索引选用情况,大致估算出找到所需的记录所需要读取的行数。

filtered:它指返回结果的行占需要读到的行(rows列的值)的百分比。表示返回结果的行数占需读取行数的百分比,filtered的值越大越好。

Extra :十分重要的额外信息

  • Using filesort :mysql对数据使用一个外部的文件内容进行了排序,而不是按照表内的索引进行排序读取 order by xxx desc这样子的,如果是索引字段的排序则不是这样的,就不需要使用外部文件了
  • Using temporary:使用临时表保存中间结果,也就是说mysql在对查询结果排序时使用了临时表,常见于order by 或 group by
  • Using index:表示相应的select操作中使用了覆盖索引(Covering Index),避免了访问表的数据行,效率高
  • Using where :使用了where过滤条件
  • select tables optimized away:基于索引优化MIN/MAX操作或者MyISAM存储引擎优化COUNT(*)操作,不必等到执行阶段在进行计算,查询执行。计划生成的阶段即可完成优化

4.mysql查询执行引擎阶段:

  调用插件式的存储引擎的原子API的功能进行执行计划的执行,执行计划的好坏也是依赖于搜索引擎的。

5.返回客户端阶段:

1、有需要做缓存的,执行缓存操作。

2、增量的返回结果:开始生成第一条结果时,mysql就开始往请求方逐步返回数据。

  好处: mysql服务器无须保存过多的数据,浪费内存。用户体验好,马上就拿到了数据。

如何定位慢SQL:

  1. 业务驱动:根据业务反馈来确定哪些sql可能出现问题。
  2. 测试驱动:通过测试确定哪些sql出现问题。
  3. 慢查询日志:通过日志记录的方式查找执行效率慢的sql。
  4. 其他第三方工具。

慢日志查询配置:

show variables like 'slow_query_log' //--查看是否开启慢日志保存
set global slow_query_log = on //-- 打开慢日志
set global slow_query_log_file = '/var/lib/mysql/gupaoedu-slow.log' //--慢日志保存位置
set global log_queries_not_using_indexes = on //-- 没有命中索引的是否要记录慢日志
set global long_query_time = 0.1 (秒) //-- 执行时间超过多少为慢日志

  可以直接打开编辑 vi slow.log文件来查看,如下图的信息:

  • Time :日志记录的时间。
  • User@Host:执行的用户及主机。
  • Query_time:查询耗费时间 Lock_time 锁表时间 Rows_sent 发送给请求方的记录,条数 Rows_examined 语句扫描的记录条数。
  • SET timestamp 语句执行的时间点。
  • select .... 执行的具体语句。

慢日志分析工具:

  mysqldumpslow -t(查询多少行) 10 -s at(平均查询时间) /var/lib/mysql/gupaoedu-slow.log

  通过返回的记录能看到前10条执行效率比较低下的sql信息,开发者可以通过这些信息去做相应的优化。

Mysql基本架构及查询流程的更多相关文章

  1. MySQL基础架构之查询语句执行流程

    这篇笔记主要记录mysql的基础架构,一条查询语句是如何执行的. 比如,在我们从student表中查询一个id=2的信息 select * from student where id=2; 在解释这条 ...

  2. mysql高级教程(一)-----逻辑架构、查询流程、索引

    mysql逻辑架构 和其它数据库相比,MySQL有点与众不同,它的架构可以在多种不同场景中应用并发挥良好作用.主要体现在存储引擎的架构上,插件式的存储引擎架构将查询处理和其它的系统任务以及数据的存储提 ...

  3. 步步深入:MySQL架构总览->查询执行流程->SQL解析顺序

    前言: 一直是想知道一条SQL语句是怎么被执行的,它执行的顺序是怎样的,然后查看总结各方资料,就有了下面这一篇博文了. 本文将从MySQL总体架构--->查询执行流程--->语句执行顺序来 ...

  4. MySQL架构总览->查询执行流程->SQL解析顺序

    Reference:  https://www.cnblogs.com/annsshadow/p/5037667.html 前言: 一直是想知道一条SQL语句是怎么被执行的,它执行的顺序是怎样的,然后 ...

  5. 步步深入MySQL:架构->查询执行流程->SQL解析顺序!

    一.前言 一直是想知道一条SQL语句是怎么被执行的,它执行的顺序是怎样的,然后查看总结各方资料,就有了下面这一篇博文了. 本文将从MySQL总体架构--->查询执行流程--->语句执行顺序 ...

  6. MySql基础架构以及SQL语句执行流程

    01. mysql基础架构 SQL语句是如何执行的 学习一下mysql的基础架构,从一条sql语句是如何执行的来学习. 一般我们写一条查询语句类似下面这样: select user,password ...

  7. mysql(一)--mysql架构和执行流程

    1. 一条查询 SQL 语句是如何执行的? 我们的程序或者工具要操作数据库,第一步要做什么事情? 跟数据库建立连接.   1.1. 通信协议 首先,MySQL 必须要运行一个服务,监听默认的 3306 ...

  8. MySQL中 如何查询表名中包含某字段的表 ,查询MySql数据库架构信息:数据库,表,表字段

    --查询tablename 数据库中 以"_copy" 结尾的表 select table_name from information_schema.tables where ta ...

  9. mysql select语句查询流程是怎么样的

    select查询流程是怎么样的 mysql select查询的数据是查询内存里面,如果没有查询的数据没有在内存,就需要mysql的innodb引擎读取磁盘,将数据加载的内存后在读取.这就体现了,mys ...

随机推荐

  1. Windows 通过批处理自动执行 linux服务器上面命令的办法

    1. 使用putty 下载地址 https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html 直接使用 exe版本就可以 https:/ ...

  2. C# Note38: Export data into Excel

    Microsoft.Office.Interop.Excel You have to have Excel installed. Add a reference to your project to ...

  3. Spring MVC 使用介绍(十)—— 编码

    一.概述 客户端与服务器端在交互过程中,需要将字符以某种编码方式转化为字节流进行传输,因此涉及字符的编码和解码.某一方以编码方案A编码,另一方须以同样的编码方案解码,否则会出现乱码. 客户端与服务器端 ...

  4. git 操作命令详解

    git 什么是git 开源的分布式版本控制系统, 用于高效的管理大小项目和文件 代码管理工具 防止代码丢失, 做备份 代码版本管控, 设置节点, 多版本切换 建立分支各自开发, 互不影响, 方便合并 ...

  5. 海亮OI学习游记

    这只是一篇纯洁的游记,这里将要记录我在海亮十天集训的生活与被虐的历史QWQ...... Day1(2.10)刚来到海亮,嗯,这的环境真的不错. 来到机房,woc这机房的配置好高啊...这里都能打守望屁 ...

  6. MTD下的Nand驱动

    目录 MTD下的Nand驱动 引入 平台设备资源文件 关键数据结构 平台框架 s3c24xx_nand_probe nand_scan s3c2410_nand_add_partition add_m ...

  7. ZooKeeper-客户端命令 zkCli

    执行 bin/zkCli 文件进入客户端 查看帮助 help ZooKeeper -server host:port cmd args stat path [watch] set path data ...

  8. 2018-2019-2 《Java程序设计》第5周学习总结

    20175319 2018-2019-2 <Java程序设计>第5周学习总结 教材学习内容总结 本周学习<Java程序设计>第六章: 接口 实现接口 接口的UML图 接口回调 ...

  9. Web概述

    Web概述 1. JavaWeb 使用java开发的基于互联网的项目 2. 软件架构 C/S:客户端服务器架构 优点:用户体验好,很多数据在本地 缺点:安装.开发.部署.维护麻烦 B/S:浏览器服务器 ...

  10. tex 字体斜体设置

    \upshape 切换成直立的字体\itshape 切换成意大利斜体\slshape 切换成成为 slanted 的斜体\scshape 切换成小体大写 http://www.tug.dk/FontC ...