SQL分类
和大多数关系型数据库一样,mysql也具有以下几种类型的SQL语句:
DML语句:主要用于新增,修改,删除和查询数据库的记录,关键字:insert,update,delete和select
DCL语句:主要用于控制数据库对象(库,表,字段、用户等对象)的访问,关键字:grant,revoke
DDL语句:主要用于定义和修改数据库对象的结构,常用关键字:create,drop,alter
注:DML(DELETE,UPDATE,SELECT)才 是我们关注的重点,而其中DELETE,UPDATE语句都可以转换为SELECT(查询)语句进行检查和优化,本ppt所有优化涉及语句默认都是SELECT语句。
SQL执行流程
客户端发送一条查询语句给服务器
服务器先会检查查询缓存,如果命中了缓存,则立即返回存储在缓存中的结果。否则进入下一阶段;
服务器端进行SQL解析、预处理,再由优化器生成对应的执行计划;
MySQL根据优化器生成的执行计划,调用存储引擎的API来执行查询;
将结果返回给客户端。
查询缓存:将sql做hash计算,将得到的hash值在查询缓存中搜索,如果存在,则校验权限,如果权限通过,将直接从缓存中获得查询的结果数据,并返回给客户端。无需进行解析、优化、执行等消耗资源的操作。
解析器:对sql语句进行语法解析,验证,比如检查是否使用错误的关键字,使用关键字的顺序是否正确等。
预处理器:在上一步完成的基础上,进一步检查数据表或数据列是否存在,字段是否存在,表的别名、字段是否有效。
查询优化器:以上步骤完成后,将开始生成执行计划,一条sql有很多种执行计划,mysql的优化器的最终会根据各种优化策略来选择和确定一条最优的执行计划。
查询执行引擎:接收到查询优化器最终确定的最优执行计划,并开始按执行计划执行,在执行过程中,会调用存储引擎(innodb,myisam,memory等)的接口来实现各种操作。
注:各种引擎共有的特性是由服务器层来实现的,比如存储过程、 触发器、各种日期时间函数和字符串函数等。
返回结果给客户端:此步为查询执行操作的最后一步,当mysql服务器处理完sql语句的所有步骤,开始生成结果时,就开始向客户端发送结果集了。当结果集全部发送完成后,此次sql语句全部执行完成。
SQL问题排查工具
- show processlist
- explain
- show index from tablename
show processlist
该工具可以简单而有效的查看当前mysql服务器的线程目前的状态,通常作为问题排查的入口之一,以下是执行结果的重点列说明:
- sid:mysql内部进程标识,通常kill语句时使用。
- user:显示当前连接用户名。
- host:显示连接是从哪个ip的哪个端口上发出的。
- db:显示这个进程目前使用是哪个数据库。
- command:显示当前连接的执行的命令,一般就是休眠(sleep),查询(query),连接(connect)。
- time:此这个状态持续的时间,单位是秒。
- state:显示使用当前连接的sql语句的状态,非常重要的列,通常为排查问题的入口。
- Info:显示这个sql语句,因为长度有限,所以长的sql语句就显示不全,full 但是一个判断问题语句的重要依据。
explain
explain结果显示MySQL如何使用处理select语句以及连接表。
- id:序号,即为sql执行的顺序。
- select_type:select类型,通常有simple,primary,union,dependent union等
- table:该步操作涉及的表
- type:连接类型,常用const,eq_ref,ref,index,ALL等
- possible_keys :提示使用哪个索引会在该表中找到行
- keys:实际执行计划使用的索引
- key_len:使用的索引长度
- ref:显示使用哪个列或常数与key一起从表中选择行。
- rows:显示MYSQL执行查询需要检查的行数。
- Extra:该列包含解决查询的重要信息,非常重要!
show index from tablename
这条命令有助于我们检查表的索引情况,是所有查询调优的基础。以下是执行结果的重点列说明:
- Table 表名。
- Non_unique 如果索引不包括重复值,则为0,否则为1。
- Key_name 索引的名称,主键的名称通常为primary。
- Seq_in_index 列在索引中位置,从1开始。
- Column_name 列的名称。
- Collation 列以什么方式存储在索引中。在MySQL中,有值‘A‘(升序)或NULL(不排序)。
- Cardinality 索引中唯一值的数目的估计值。基数越大,当进行关联查询时,MySQL使用该索引的机会就越大。
- Sub_part 如果列只是被部分值索引,则为索引列的字符的数目。如果整列被索引,则为NULL。
- Null 如果列有NULL值,则为YES。如果没有null值,则该列含有NO。
- Index_type 索引的类型(BTREE, FULLTEXT, HASH, RTREE)。