MySQL单条SQL语句性能评估 如何分析一条sql语句的性能

   2023-02-09 学习力0
核心提示:MySQL单条SQL语句性能评估-基于《High Performance MySQL》第五章Profiling a Single Query很不幸,大部分MySQL指令对于评估一条SQL语句都不是很给力。虽然MySQL在这方面正在努力,不过目前为止,实际最好用的只有这两个命令:SHOW STATUS和SHOW PROFILE。SHO

MySQL单条SQL语句性能评估

-基于《High Performance MySQL》第五章Profiling a Single Query

很不幸,大部分MySQL指令对于评估一条SQL语句都不是很给力。虽然MySQL在这方面正在努力,不过目前为止,实际最好用的只有这两个命令:SHOW STATUS和SHOW PROFILE。

SHOW PROFILE命令

这个命令来自社区贡献,由Jeremy Cole提供,集成到了5.1以后的版本中。默认是没有开启这个命令支持的,需要用SET profiling = 1;来开启。开启以后,会输出任何命令的耗时和执行过程中的状态变化。每次执行命令的时候,评估数据会被记录到一个临时表中,这个表可以通过SHOW PROFILES;来看:

MySQL单条SQL语句性能评估

接着可以 SHOW PROFILE FOR QUERY 1;

MySQL单条SQL语句性能评估
评估表保存了SQL语句执行的每一步子过程耗时。这样直接从头到尾列出来不是很容易发现问题,可以用SQL计算做一个计算:

>SET @query_id = 1;

>SELECT STATE, SUM(DURATION) AS Total_R,

ROUND(
-> 100 * SUM(DURATION) /
-> (SELECT SUM(DURATION)
-> FROM INFORMATION_SCHEMA.PROFILING
-> WHERE QUERY_ID = @query_id
-> ), 2) AS Pct_R,
-> COUNT(*) AS Calls,
-> SUM(DURATION) / COUNT(*) AS "R/Call"
-> FROM INFORMATION_SCHEMA.PROFILING
-> WHERE QUERY_ID = @query_id
-> GROUP BY STATE
-> ORDER BY Total_R DESC;

得到:

MySQL单条SQL语句性能评估

这样更容易发现最耗时的操作并针对性得调整SQL语句。有些过程比如"Sending Data",很难对应到具体如何优化,因为每一步操作基本都会涉及到发送数据,这种就只能先放放了。虽然我们得到了更细化的执行耗时,但其实这个命令不会告诉我们某个子工程为什么耗时。比如想要知道为什么"copying to tmp table"拷贝数据到临时表花了那么多时间,需要更进一步对这个子过程进行评估。

SHOW STATUS命令

SHOW STATUS返回各种计数,这些值有全局的(整个MySQL服务器),也有Session的(本次连接)。而如果用SHOW GLOBAL STATUS返回的计数都是全局的。SHOW STATUS返回的计数中哪些是全局的,哪些是本Session的,需要参考MySQL手册。

SHOW STATUS不是真的评估工具,它仅仅返回MySQL的各种活动的计数。这些计数中只有一个Innodb_row_lock_time表示的时间,并且计数是全局的,所以也没啥用。

所以我们要结合一个SQL语句执行的前后计数来猜测哪些动作比较耗费时间。最重要的计数是handler counters 和 temporary file and table counters。让我们先把计数清零,看看这个例子:

> FLUSH STATUS;

> SELECT * FROM sakila.nicer_but_slower_film_list;

> SHOW STATUS WHERE Variable_name LIKE 'Handler%'

OR Variable_name LIKE 'Created%';

MySQL单条SQL语句性能评估

MySQL单条SQL语句性能评估

大概可以看出,这个SQL执行过程中,用了3次临时表——其中两个表在磁盘上,做了很多没有索引加速的都操作(Handler_read_rnd_next)。从这个结果猜测,可能这个select查询了一个view,此view需要执行一个未加索引的join。

要注意SHOW STATUS操作本身自己就会出发一些计数增加,比如说写两次表格,所以前面一条SQL语句对应的临时表的操作计数应该在结果上减去2。

这得注意的是,SHOW STATUS得到的信息可能和EXPLAIN差不多,但EXPLAIN只是预测,并不是真是执行的结果。EXPLAIN不会告诉你临时表是在内存还是在磁盘这种重要信息。

耗时SQL语句日志

MySQL可以在日志中记录耗时的SQL操作,Percona Server(MySQL fork出来的另外开源实现)记录的更细。以SHOW PROFILE章节中的SQL语句为例,Log是这样的:

MySQL单条SQL语句性能评估从中可以看出,这条语句执行过程中创建了3个临时表,其中两个表在磁盘上。

相比于SHOW STATUS和SHOW PROFILE,耗时SQL语句日志记录更详细的信息,特别是配合pt-query-digest日志分析工具,你可以从日志中方便找到对应的SQL语句的位置。Pt-query-digist可以为SQL语句输出统计头:

# Query 1: 0 QPS, 0x concurrency, ID 0xEE758C5E0D7EADEE at byte 3214 _____

然后用shell命令就能从日志文件中拉出对应的日志:

tail -c +3214 /path/to/query.log | head -n100

全局性能统计(Performance Schema)

全局性能统计在MySQL5.5中开始引入,虽然5.5版本中不支持SQL语句级别的统计,但还是能提供一些有用的信息,比如:

> SELECT event_name, count_star, sum_timer_wait

-> FROM events_waits_summary_global_by_event_name

-> ORDER BY sum_timer_wait DESC LIMIT 5;

得到:

MySQL单条SQL语句性能评估

5.6以后的版本,应该会更有用。

 
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • sql:mysql:函数:TIMESTAMPDIFF函数实现TimeStamp字段相减,求得时间差
    sql:mysql:函数:TIMESTAMPDIFF函数实现TimeS
     函数内指定是minute,则最终结果value值的单位是分钟,如果函数内指定为hours,则最终结果value值单位为小时。//UPLOAD_TIME 减去 CREATE_DTTM 求得时间差,以分钟数计时select avg(TIMESTAMPDIFF(MINUTE,CREATE_DTTM,UPLOAD_TIME)) value,LEFT(CREATE_DTTM
    03-08
  • 去重复的sql(Oracle) 去重复的英文
    1.利用group by 去重复2.可以利用下面的sql去重复,如下  1) select id,name,sex from (select a.*,row_number() over(partition by a.id,a.set order by name) su from test a ) where su=1  2)select id,name,sex from (select a.*,row_number() over(p
    02-10
  • Oracle SQL七次提速技巧
    以下SQL执行时间按序号递减。1,动态SQL,没有绑定变量,每次执行都做硬解析操作,占用较大的共享池空间,若共享池空间不足,会导致其他SQL语句的解析信息被挤出共享池。create or replace procedure proc1as beginfor i in 1..100000 loop    execute imme
    02-10
  • Oracle\SQL  Server等及其他基本语句写法
    Oracle\SQL Server等及其他基本语句写法
    Oracle\SQL  Server等及其他基本语句写法目录一.Excel相关 11.Excel中写脚本范例: 12.提取字节 23. 提取单元格内字符 24.VLOOKUP函数: 2二.SQL语句汇总 21.建表: 22.增 33.删 44.查 65.改 236.Alter的应用 24三.数据库备份与恢复脚本 261. Oracle: 2
    02-10
  • SQL ORACLE case when函数用法
    case when 用法(1)简单case函数:格式:  case 列名   when 条件值1 then 选项1  when 条件值1 then 选项2......  else 默认值 end例如:  select   case job_level  when '1' then '1111'  when '2' then '2222'   when '3' then '3333
    02-10
  • mysql下如何执行sql脚本 执行SQL脚本
    1.编写sql脚本,假设内容如下:  create database dearabao;  use dearabao;  create table niuzi (name varchar(20));  保存脚本文件,假设我把它保存在F盘的hello world目录下,于是该文件的路径为:F:\hello world\niuzi.sql2.执行sql脚本,可以有2种方法: 
    02-10
  • MySQL 5.7版本sql_mode=only_full_group_by问题
    用到GROUP BY 语句查询时com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'col_user_6.a.START_TIME' which is not functionally dependent on colu
    02-10
  • Oracle迁移到MySQL性能下降的注意点 oracle数据
    背景:最近有较多的客户系统由原来由Oracle改造到MySQL后出现了性能问题CPU 100%,或是后台的CRM系统复杂SQL在业务高峰的时候出现堆积导致业务故障。在我的记忆里面淘宝最初从Oracle迁移到MySQL期间也遇到了很多SQL的性能问题,记忆最为深刻的子查询,当初的
    02-10
  • ORACLE中通过SQL语句(alter table)来增加、删除
    1.添加字段:alter table  表名  add (字段  字段类型)  [ default  '输入默认值']  [null/not null]  ;2.添加备注:comment on column  库名.表名.字段名 is  '输入的备注';  如: 我要在ers_data库中  test表 document_type字段添加备注  comm
    02-10
  • MySQL与Oracle 差异比较之六触发器
    触发器编号类别ORACLEMYSQL注释1创建触发器语句不同create or replace trigger TG_ES_FAC_UNIT  before insert or update or delete on ES_FAC_UNIT  for each rowcreate trigger `hs_esbs`.`TG_INSERT_ES_FAC_UNIT` BEFORE INSERT on `hs_esbs`.`es_fac_u
    02-10
点击排行