MySQL --- SQL解析 与 性能分析工具

  • 一. SQL解析及优化

1 . SQL解析

SQL进入引擎的流程

 

Eg:select XXX  from ….join …on …where  ….group by …having …order by …limit

解析顺序:from …on..join … where …group by …having …select …order by .limit

1.1 sql在MySQL服务上的执行流程

参考:www.cnblogs.com/annsshadow/p/5037667.html

      dev.mysql.com/doc/refman/5.7/en/memory-use.html

2. 优化工具:

    1. Explain 执行计划使用方法

2.1.1. explain 结果参数说明

Eg:优化前SQL:

explain select a.account_id ,a.user_id ,a.course_id

from  study_right_logger_11 a  join user b on a.user_id = b.user_id

 where   a.account_id = '60258144'  or a.course_id= '124162'  ;

备注:study_right_logger_11 建立符合索引顺序:`account_id`, `course_id`, `user_id`

(1).

结果参数

参数类型

作用

含义

id

Id值相同:从上往下顺序执行,数据少的表优先查询

Sql中table的执行顺序

表的执行顺序因表的行数的变化而改变:笛卡尔积

Id值不同越大越优先查询(有子查询时)

 

 

Select_type

Primary:

包含子查询SQL的主查询,最外层

 

Subquery:

包含子查询SQL的子查询,非最外层

 

Simple

不包含:子查询和union

 

Derived:衍生查询

使用了临时表

  1. 在from 子查询中只有一张表
  2. 在from的子查询中如果有talble1 union table2 ,则table1就是derived

 

Union:

衍生表,如下图1

 

Table

Derived + id(衍生表)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Type

system

理想情况,实际达不到。只有一条数据的系统表或衍生表只有一条数据的主查询.eg:select * from (

Select * from test1)t where tid =1; test1中只有一条数据

索引类型

const

仅能查到一条数据是SQL

用于primary key 或unique索引

结果仅有一条数据

eq_ref

唯一性索引,对于每个索引键的查询,返回匹配唯一行数据,有且只有1个不能为0( 如果表中的索引列有没查询出来的数据则认为是0 ,即全部索引列必须全部查询出来,基本很难满足)。

即索引列的每个值都是唯一的,eg:name 全是唯一的,且是索引列

结果是多条数据,但每条数据唯一

ref

非唯一性索引,对于每个索引键的查询返回匹配的所有行。

结果是多条,(0 或者多条)

range

查询指定范围的行,where后面是一个范围查询(between,< ,> ,in 有时会失效,转为无索引)

 

Index

查询全部索引数据

 

 

all

查询全部表中的数据,全表扫描

 

Index_merge

MySQL5.0之前,一个表一次只能使用一个索引,无法同时使用多个索引分别进行条件扫描。但是从5.1开始,引入了 index merge 优化技术,对同一个表可以使用多个索引分别进行条件扫描

 

index merge intersect

 

Possible_keys

具体索引列

 

表示可能用到的索引,是一种预测

 

Null

没有使用索引

 

key

 

 

实际使用到的索引

 

 

 

 

Key_len

索引的长度

如果长度是0 ,则该索引列未被使用,用于判断符合索引是否完全被使用

( a,b,c )三个列的符合索引

符合索引如果要使用后面的列的索引则必然前面是索引也要使用

Utf-8:1个字符占用3个字节

A.如果列 是char(10 )则该列占3 * 10

B.如果索引字段可以为null,则会使用1个字节用于标识

C.如果类型是varchar 则除了有一位null的标识,还会用2个字节标识可变长度。即最后多出3位

C. int型占用4个字节,索引中只包含了1列,所以,key_len是4

 

D .

ref

Const

 

当前表所参照的字段

 

 

 

 

 

 

rows

整数

 

通过索引查询到的数据行数

 

 

 

extra

(一)

Using filesout

性能消耗很大,SQL需要优化

 

Eg:select * from table1 where a1 = XX order by a2 ; 即:using filesout.

A.对于单索引,如果排序和查询的列是同一个字段则不会出现using filesout ;如果排序和查询不是同一个字段,则需要额外查询,则是using filesout

 

 

B.复合索引:不能跨列

Eg:( a1,a2,a3)复合索引列

Select * from table where a1=XX order by a3;

a1跟a3跨列了,

Select * from table where a2=XX order by a3;

a1被跨了,同样是using filesout

 

Where 和orderby 按照复合索引的顺序使用,不要跨列

 

(二)

Using temporary:同样性能损耗很大,用到了临时表,常出现在group by

Eg:select a1 from table where a1 in( 1,2,3 ) group by a2;

查询的a1 但是根据a2分组,会导致MySQL再创建临时表查询结果

则extra 就是Using temporary,所以要查询和排序列一致

注:解析过程

From..on..join..where..group by..having..select distinct ..orderby limit…

Eg:select * from table where a2=2 and a4=4 group by a2,a4 ;--没有using temporary

 

Select * from table where a2 =2 and a4=4 group by a3;using temporary

 

 

 

(三)

Using index 性能提升的标识—索引覆盖

说明当前的SQL不读取原文件,只从索引文件获取数据,不需要回表查询

只要查询的列全部都在索引中就会是using index

Eg:复合索引( a1, a2,a3 )

Select a1,a2 from table where a1 =XX and a2=XXX

上面的SQL就会使用using index

 

 

 

 

 

 

 

 

(四)

Using where :需要回表查询

Eg:a1 是索引列

Select a1,a2 from table where a1=XX

上面是SQL必须回原表查询a2

 

也有特殊情况,MySQL底层的优化器也会帮助优化SQL语句

Eg:复合索引:a1,a2,a3

Select a1,a2,a3 from table where a2=X and a1=x and a3=xx;

上面虽然跟复合索引顺序不一致,但也是using index 是因为SQL优化器的结果

 

Eg:复合索引:a1,a2,a3

Select a1,a2,a3 from table where a1=1 and a3=3 order by a2;

结果是:Using index + Using where

A1在索引中可以直接查询,但a3无效因为跨列了,则需要回表查询(using where )

 

 

 

五.

using index condition:查找使用了索引,但是需要回表查询数据

 

 

 

六.

using intersect:表示使用and的各个索引的条件时,该信息表示是从处理结果获取交集

using union:表示使用or连接各个使用索引的条件时,该信息表示从处理结果获取并集

using sort_union和using sort_intersection:与前面两个对应的类似,只是他们是出现在用and和or查询信息量大时,先查询主键,然后进行排序合并后,才能读取记录并返回。

 

七.using join buffer

mysql 引擎使用了连接缓存,说明SQL质量很差

 

 

 

 

 

2.2  profile

mysql5.0.3版本以后才开放的。但是在mysql5.7之后,profile信息将逐渐被废弃,mysql推荐使用performance schema

2.2.1. 开启使用

可以定位SQL执行过程中对CPU和io的消耗

(1)方法一

     

   A.查看是否启用:SELECT @@profiling;

                开启profile :SET profiling = 1; //临时打开,而不是全局打开

      当打开后,所有的SQL语句全部记录

   B. 查看记录 :query :show profile for query 1; // 数字表示查询的ID

      备注:在使用profile查看执行过程记录之前要先把profile关闭掉,即:

                  SET profiling = 0;

   C. show profile cpu,block io,memory,swaps for query 查询ID;

   D.用show profiles;可以查询之前操作SQL对应的ID值

缺点:消耗性能,在生产环境是关闭的

(2)方法二:查询全局日志,记录了开启后的全部SQL日志

     查看命令:show variables like '%general_log%';

     打开全局日志命令:set global general_log=1; 或等2

      文件会记录:mysql.general_log  ( mysql 库的general_log 表 )

2.2.2 查询参数

备注:使用select @@ mysql的配置参数名称,就可以查询出该参数对应的具体值

Eg:

如果IO的in和out 都是0 说明数据都已经被缓存在内存中了。

2.3.performance_schema 系统级存储引擎

2.3.1. 介绍

A.MySQL的performance schema 用于监控MySQL运行过程中的资源消耗、资源等待等情况。主要关注数据库运行过程中的性能相关的数据,与information_schema不同,information_schema主要关注server运行过程中的元数据信息

B.提供了一种在数据库运行时实时检查server的内部执行情况的方法。performance_schema 数据库中的表使用performance_schema存储引擎。该数据库主要关注数据库运行过程中的性能相关的数据

C.server内部活动中所做的任何事情以及对应的时间消耗

Dperformance_schema中的事件只记录在本地serverperformance_schema中,其下的 这些表中数据发生变化时不会被写入binlog中,也不会通过复制机制被复制到其他server

Eperformance_schema的表中的数据不会持久化存储在磁盘中,而是保存在内存中,一旦服务器重启,这些数据会丢失

 

2.3.2. 使用介绍

2.3.2.1.查询当前MySQL的实例是否支持,

命令:show engines;

2.3.2.2.performance_schema被视为存储引擎

查看是否支持命令:

SELECT * FROM INFORMATION_SCHEMA.ENGINES WHERE ENGINE ='PERFORMANCE_SCHEMA';

2.3.2.3.启用方法

   performance_schema5.7.x及其以上版本中默认启用(5.6.x及其以下版本默认关闭),如果要显式启用或关闭时,我们需要使用参数performance_schema=ON|OFF设置,并在my.cnf中进行配置

   [mysqld]

performance_schema = ON  # 注意:该参数为只读参数,需要在实例启动之前设置才生效

2.3.2.4.查询是否开启,

命令:SHOW VARIABLES LIKE 'performance_schema';

2.3.2.5.查询引擎涉及到的所有表:

   performance_schema引擎相关的元数据来了解在performance_schema下存在着哪些表:

   命令:SELECT * FROM INFORMATION_SCHEMA.TABLES

WHERE TABLE_SCHEMA ='performance_schema' and engine='performance_schema';

2.3.3. performance_schema表的分类

performance_schema库下的表可以按照监视不同的纬度进行了分组,例如:或按照不同数据库对象进行分组,或按照不同的事件类型进行分组,或在按照事件类型分组之后,再进一步按照帐号、主机、程序、线程、用户等

2.3.3.1. 事务相关

事务事件记录表,记录事务相关的事件的表,与语句事件类型的相关记录表类似:

A.查询语句:show tables like 'events_transaction%';

B.作用:

2.3.3.2.内存相关

A.查询语句: show tables like 'events_transaction%';

 

2.3.3.3. 等待事件记录相关

A.查询语句:show tables like 'events_wait%';

 

+-----------------------------------------------+

| Tables_in_performance_schema (%wait%)         |

+-----------------------------------------------+

| events_waits_current                          |

| events_waits_history                          |

| events_waits_history_long                     |

| events_waits_summary_by_account_by_event_name |

| events_waits_summary_by_host_by_event_name    |

| events_waits_summary_by_instance              |

| events_waits_summary_by_thread_by_event_name  |

| events_waits_summary_by_user_by_event_name    |

| events_waits_summary_global_by_event_name    

 

2.3.3.4. 阶段事件记录相关

A.查询语句:show tables like 'events_stage%';

都是events_stages_* 开头的表

 

 

2.3.4. 运行时配置

2.3.4.1. 开启配置

A.在引擎启动时并非所有表instruments(事件采集项,在采集项的配置表中每一项都有一个开关字段YESNO)consumers(与采集项类似, YES就表示对应的表保存性能数据,为NO就表示对应的表不保存性能数据)都启用了。需要手动开启收集配置。

B.打开等待事件的采集器配置项开关,需要修改setup_instruments 配置表中对应的采集器配置项

   开启语句:UPDATE setup_instruments SET ENABLED = 'YES', TIMED = 'YES' where name  like 'wait%';

C.打开等待事件的保存表配置开关,修改修改setup_consumers 配置表

   开启语句:UPDATE setup_consumers SET ENABLED = 'YES' where name like '%wait%';

 

D.其他事件都类似

 

2.3.5. 应用:监控查询例子

2.3.5.1.查询连接数据库实例的线程连接数量及账号

select * from performance_schema.accounts;

  1. current_connections :当前连接数
  2. total_connections:总连接数

2.3.5.2.查询SQL执行时长的历史记录

 SELECT EVENT_ID, TRUNCATE(TIMER_WAIT/1000000000000,6) as Duration, SQL_TEXT   FROM performance_schema.events_statements_current where SQL_TEXT IS NOT NULL AND SQL_TEXT <> 'BEGIN';

你可能感兴趣的:(数据库)