转自:http://www.percona.com/blog/2015/04/16/profiling-mysql-queries-from-performance-schema/

When optimizing queries and investigating performance issues, MySQL comes with built in support for profiling queries aka SET profiling = 1; . This is already awesome and simple to use, but why the PERFORMANCE_SCHEMA alternative?

Because profiling will be removed soon (already deprecated on MySQL 5.6 ad 5.7); the built-in profiling capability can only be enabled per session. This means that you cannot capture profiling information for queries running from other connections. If you are using Percona Server, the profiling option for log_slow_verbosity is a nice alternative, unfortunately, not everyone is using Percona Server.

Now, for a quick demo: I execute a simple query and profile it below. Note that all of these commands are executed from a single session to my test instance.

mysql> SHOW PROFILES;
+----------+------------+----------------------------------------+
| Query_ID | Duration | Query |
+----------+------------+----------------------------------------+
| 1 | 0.00011150 | SELECT * FROM sysbench.sbtest1 LIMIT 1 |
+----------+------------+----------------------------------------+
1 row in set, 1 warning (0.00 sec)
mysql> SHOW PROFILE SOURCE FOR QUERY 1;
+----------------------+----------+-----------------------+------------------+-------------+
| Status | Duration | Source_function | Source_file | Source_line |
+----------------------+----------+-----------------------+------------------+-------------+
| starting | 0.000017 | NULL | NULL | NULL |
| checking permissions | 0.000003 | check_access | sql_parse.cc | 5797 |
| Opening tables | 0.000021 | open_tables | sql_base.cc | 5156 |
| init | 0.000009 | mysql_prepare_select | sql_select.cc | 1050 |
| System lock | 0.000005 | mysql_lock_tables | lock.cc | 306 |
| optimizing | 0.000002 | optimize | sql_optimizer.cc | 138 |
| statistics | 0.000006 | optimize | sql_optimizer.cc | 381 |
| preparing | 0.000005 | optimize | sql_optimizer.cc | 504 |
| executing | 0.000001 | exec | sql_executor.cc | 110 |
| Sending data | 0.000025 | exec | sql_executor.cc | 190 |
| end | 0.000002 | mysql_execute_select | sql_select.cc | 1105 |
| query end | 0.000003 | mysql_execute_command | sql_parse.cc | 5465 |
| closing tables | 0.000004 | mysql_execute_command | sql_parse.cc | 5544 |
| freeing items | 0.000005 | mysql_parse | sql_parse.cc | 6969 |
| cleaning up | 0.000006 | dispatch_command | sql_parse.cc | 1874 |
+----------------------+----------+-----------------------+------------------+-------------+
15 rows in set, 1 warning (0.00 sec)

To demonstrate how we can achieve the same with Performance Schema, we first identify our current connection id. In the real world, you might want to get the connection/processlist id of the thread you want to watch i.e. from SHOW PROCESSLIST .

mysql> SELECT THREAD_ID INTO @my_thread_id
-> FROM threads WHERE PROCESSLIST_ID = CONNECTION_ID();
Query OK, 1 row affected (0.00 sec)

Next, we identify the bounding EVENT_IDs for the statement stages. We will look for the statement we wanted to profile using the query below from the events_statements_history_long table. Your LIMIT clause may vary depending on how much queries the server might be getting.

mysql> SELECT THREAD_ID, EVENT_ID, END_EVENT_ID, SQL_TEXT, NESTING_EVENT_ID
-> FROM events_statements_history_long
-> WHERE THREAD_ID = @my_thread_id
-> AND EVENT_NAME = 'statement/sql/select'
-> ORDER BY EVENT_ID DESC LIMIT 3 G
*************************** 1. row ***************************
THREAD_ID: 13848
EVENT_ID: 419
END_EVENT_ID: 434
SQL_TEXT: SELECT THREAD_ID INTO @my_thread_id
FROM threads WHERE PROCESSLIST_ID = CONNECTION_ID()
NESTING_EVENT_ID: NULL
*************************** 2. row ***************************
THREAD_ID: 13848
EVENT_ID: 374
END_EVENT_ID: 392
SQL_TEXT: SELECT * FROM sysbench.sbtest1 LIMIT 1
NESTING_EVENT_ID: NULL
*************************** 3. row ***************************
THREAD_ID: 13848
EVENT_ID: 353
END_EVENT_ID: 364
SQL_TEXT: select @@version_comment limit 1
NESTING_EVENT_ID: NULL
3 rows in set (0.02 sec)

From the results above, we are mostly interested with the EVENT_ID and END_EVENT_ID values from the second row, this will give us the stage events of this particular query from the events_stages_history_long table.

mysql> SELECT EVENT_NAME, SOURCE, (TIMER_END-TIMER_START)/1000000000 as 'DURATION (ms)'
-> FROM events_stages_history_long
-> WHERE THREAD_ID = @my_thread_id AND EVENT_ID BETWEEN 374 AND 392;
+--------------------------------+----------------------+---------------+
| EVENT_NAME | SOURCE | DURATION (ms) |
+--------------------------------+----------------------+---------------+
| stage/sql/init | mysqld.cc:998 | 0.0214 |
| stage/sql/checking permissions | sql_parse.cc:5797 | 0.0023 |
| stage/sql/Opening tables | sql_base.cc:5156 | 0.0205 |
| stage/sql/init | sql_select.cc:1050 | 0.0089 |
| stage/sql/System lock | lock.cc:306 | 0.0047 |
| stage/sql/optimizing | sql_optimizer.cc:138 | 0.0016 |
| stage/sql/statistics | sql_optimizer.cc:381 | 0.0058 |
| stage/sql/preparing | sql_optimizer.cc:504 | 0.0044 |
| stage/sql/executing | sql_executor.cc:110 | 0.0008 |
| stage/sql/Sending data | sql_executor.cc:190 | 0.0251 |
| stage/sql/end | sql_select.cc:1105 | 0.0017 |
| stage/sql/query end | sql_parse.cc:5465 | 0.0031 |
| stage/sql/closing tables | sql_parse.cc:5544 | 0.0037 |
| stage/sql/freeing items | sql_parse.cc:6969 | 0.0056 |
| stage/sql/cleaning up | sql_parse.cc:1874 | 0.0006 |
+--------------------------------+----------------------+---------------+
15 rows in set (0.01 sec)

As you can see the results are pretty close, not exactly the same but close. SHOW PROFILE shows Duration in seconds, while the results above is in milliseconds.

Some limitations to this method though:

  • As we’ve seen it takes a few hoops to dish out the information we need. Because we have to identify the statement we have to profile manually, this procedure may not be easy to port into tools like the sys schema or pstop.
  • Only possible if Performance Schema is enabled (by default its enabled since MySQL 5.6.6, yay!)
  • Does not cover all metrics compared to the native profiling i.e. CONTEXT SWITCHES, BLOCK IO, SWAPS
  • Depending on how busy the server you are running the tests, the sizes of the history tables may be too small, as such you either have to increase or loose the history to early i.e. performance_schema_events_stages_history_long_size variable. Using ps_history might help in this case though with a little modification to the queries.
  • The resulting Duration per event may vary, I would think this may be due to the additional as described on performance_timers table. In any case we hope to get this cleared up as result when this bug is fixed.

Profiling MySQL queries from Performance Schema的更多相关文章

  1. MySQL 5.7 Performance Schema 详解

    refman mysql 5.7 MySQL Performance Schema  用于监视MySQL服务器,且运行时消耗很少的性能.Performance Schema 收集数据库服务器性能参数, ...

  2. [MySQL Reference Manual] 23 Performance Schema结构

    23 MySQL Performance Schema 23 MySQL Performance Schema 23.1 性能框架快速启动 23.2 性能框架配置 23.2.1 性能框架编译时配置 2 ...

  3. Mysql之performance Schema

    Performance schema是用于监控Mysql执行,具有如下特征: 1.用于在运行时探查Mysql Server的执行过程,是由Performance_schema引擎和 Performan ...

  4. MySQL调优性能监控之performance schema

    一.performance_schema的介绍 performance:性能 schema:图(表)示,以大纲或模型的形式表示计划或理论. MySQL的performance schema 用于监控M ...

  5. MySQL Performance Schema详解

    MySQL的performance schema 用于监控MySQL server在一个较低级别的运行过程中的资源消耗.资源等待等情况. 1 performance schema特点 提供了一种在数据 ...

  6. 通过performance schema收集慢查询

    MySQL5.6起performance schema自动开启,里面涉及记录 statement event的表 mysql> show tables like '%statement%'; + ...

  7. mysql performance schema的即时诊断工具-邱伟胜

    https://github.com/noodba http://www.noodba.com

  8. 【MySQL】MySQL 5.7 sys Schema

    sys库说明:http://dev.mysql.com/doc/refman/5.7/en/sys-schema-usage.html sys库使用说明:http://dev.mysql.com/do ...

  9. MySql(九):MySQL性能调优——Schema设计的性能优化

    一.高效的模型设计 先了解下数据库设计的三大范式 第一范式:要求有主键,并且要求每一个字段原子性不可再分 第二范式:要求所有非主键字段完全依赖主键,不能产生部分依赖 第三范式:所有非主键字段和主键字段 ...

随机推荐

  1. Java魔法堂:注解用法详解——@Override

    一.前言 现在有Son和Parent两个类,且类型Son将会重写类型Parent的getName函数.但不幸的是由于码农大意,写成如下代码: public class Parent{ public S ...

  2. Gradle学习系列之十——自定义Plugin(本系列完)

    在本系列的上篇文章中,我们讲到了如何自定义Task类型,在本篇文章中,我们将讲到如何自定义Plugin. 请通过以下方式下载本系列文章的Github示例代码: git clone https://gi ...

  3. Protocol Buffers动态消息解析

    http://www.searchtb.com/2012/09/protocol-buffers.html http://www.cnblogs.com/jacksu-tencent/p/344731 ...

  4. 无法打开Android SDK Manager的解决办法

    不知道从什么时候开始,打开Android的SDK Manager.exe时,命令行窗口一闪就自动关掉了. 想更新一些Android的东西都更新不了. 查了一下,解决办法是: 环境变量的系统变量Path ...

  5. 树状数组--K.Bro Sorting

    题目网址: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=110064#problem/D Description Matt’s frie ...

  6. YII页面跳转

    $criteria = new CDbCriteria; $criteria->select = array('ziduan"); $res = Model::model()-> ...

  7. 面向企业客户的制造业CRM系统的不成熟思考

    CRM就是客户关系管理(Customer Relationship Management),一直一知半解,最近有涉及这方面的需求,所以稍作研究,并思考一些相关问题. CRM是什么? CRM具体如何定义 ...

  8. C#中List<T>对象的深度拷贝问题

    一.List<T>对象中的T是值类型的情况(int 类型等) 对于值类型的List直接用以下方法就可以复制: List<T> oldList = new List<T&g ...

  9. winform(容器、打印、对话框)

    一.布局:2个属性:Anchor:锁定位置Dock:填充位置一般Dock是与容器控件配合使用 二.容器控件:Panel:就是一个区域,类似于DIV,可以独立布局,还可以让其它控件及容器在它的内部再次布 ...

  10. SQL数据库基础(四)

    聚合函数:sum,avg,max,min,count 使用方法示例: group by  分组的使用方法 分组的练习: 数学函数:ABS.ceiling.floor.power.round.sqrt. ...