Profiling MySQL queries from Performance Schema

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

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.
时间: 2024-08-08 19:57:41

Profiling MySQL queries from Performance Schema的相关文章

[MySQL Reference Manual] 23 Performance Schema结构

23 MySQL Performance Schema 23 MySQL Performance Schema.. 1 23.1 性能框架快速启动... 3 23.2 性能框架配置... 5 23.2.1 性能框架编译时配置... 5 23.2.2 性能框架启动配置... 6 23.2.3 启动时性能框架配置... 8 23.2.3.1 性能架构事件定时... 8 23.2.3.2 性能框架事件过滤... 9 23.2.3.3 事件预过滤... 10 23.2.3.4命名记录点或者消费者的过滤.

通过performance schema收集慢查询

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

高性能MySQL(四)—Schema与数据类型优化(1)

Schema与数据类型优化 选择优化的数据类型 下面是一些简单的原则: 更小的通常更好 一般情况下,应该尽量使用可以正确存储的最小数据类型.如:只需要存储0-200, tinyint unsigned就比较好.小的数据类型占的磁盘.内存和CPU缓存都较少,并且处理时需要的CPU周期数也更少. 简单就好 简单数据类型额操作通常需要更少的CPU周期.如:应该使用MySQL的內建类型来存储时间和日期而不是字符串.如:应该用整型存储IP地址. 尽量避免null 通常情况下最好指定列为NOT NULL,除

高性能mysql 第4章 Schema与数据类型优化

基本原则: 更小的通常更好:占用更少的磁盘 内存和cpu缓存. 简单就好:比如整形比字符型代价更低.使用日期型来存储日期而不是字符串.使用整形存储ip地址. 尽量避免null:如果可以 加上not null约束.因为可以null的列使索引,索引统计,值比较都变得复杂.通常把可为null的列改为not null带来的性能提升比较小,调优时没有必要首先修正这种情况来排查问题.但是如果计划在列上建立索引,如果可以保证是not null,那么尽量加上. 整数类型: tinyint,smallint.,m

How can I view currently running MySQL queries?( 查看正在运行的MySQL语句/脚本命令)

show processlist;show processlist\G;SHOW FULL PROCESSLIST;SHOW FULL PROCESSLIST\G; REF:http://dev.mysql.com/doc/refman/5.7/en/show-processlist.htmlhttp://stackoverflow.com/questions/568564/how-can-i-view-live-mysql-queries

Oracle MySQL Server组件Information Schema子组件远程漏洞(CVE-2012-3163)

MySQL是一个小型关系型数据库管理系统,开发者为瑞典MySQLAB公司,在2008年1月16号被Sun公司收购. Oracle MySQL Server组件的实现上存在安全漏洞,通过MySQL协议,已经验证的远程攻击者可利用此漏洞影响下列版本的完整性.可用性.机密性: 5.1.64及更早版本.5.5.26及更早版本 <*来源:Oracle 链接:http://www.oracle.com/technetwork/topics/security/cpuoct2012-1515893.html *

Mysql in statement performance related with its position?

select * from ( select event_date, '2014-12-06' as active_date, channel_id, new_user_count as new_user_count, 1d_retain/new_user_count as 1d_retain_rate from web_channel_retain where app_id=-1 and event_date='2014-12-05' and new_user_count>= 500 and

Mysql分析-profile详解

一.前言当我们要对某一条sql的性能进行分析时,可以使用它. Profiling是从 mysql5.0.3版本以后才开放的.启动profile之后,所有查询包括错误的语句都会记录在内.关闭会话或者set profiling=0 就关闭了.(如果将profiling_history_size参数设置为0,同样具有关闭MySQL的profiling效果.) 此工具可用来查询SQL执行状态,System lock和Table lock 花多少时间等等, 对定位一条语句的I/O消耗和CPU消耗 非常重要

MySQL5.7中 performance和sys schema中的监控参数解释

MySQL5.7中的mysql  performance和sys 监控参数 1.performance schema:介绍 在MySQL5.7中,performance schema有很大改进,包括引入大量新加入的监控项.降低占用空间和负载,以及通过新的sys schema机制显著提升易用性.在监控方面,performance schema有如下功能: ①:元数据锁: 对于了解会话之间元数据锁的依赖关系至关重要.从MySQL5.7.3开始,就可以通过metadata_locks表来了解元数据锁的