zoukankan      html  css  js  c++  java
  • MySQL 查看SQL语句执行阶段和进度信息

    测试MySQL版本:5.7.31
    根据《MySQL性能优化金字塔法则》做的实验,好书推荐!

    我们在创建索引时,经常需要等待执行的SQL一段时间,期间可以通过此方法查看SQL的执行进度等信息。

    首先要开启收集执行阶段信息的功能,与统计汇总执行阶段信息的功能

    # 会话1
    update performance_schema.setup_instruments 
    set enabled='yes', timed='yes' where name like 'stage/%';
    
    update performance_schema.setup_consumers 
    set enabled='yes' where name like '%stage%';
    

    我们需要确定执行的SQL所属的thread_id。这里我们新起一个会话2进行模拟,查询会话2的thread_id

    # 会话2
    mysql> select sys.ps_thread_id(connection_id());
    +-----------------------------------+
    | sys.ps_thread_id(connection_id()) |
    +-----------------------------------+
    |                             93315 |
    +-----------------------------------+
    

    一般来说,肯定会有许多线程同时存在,我们只对所希望监控的线程启用监控,将其他线程收集执行阶段信息的功能关闭

    # 会话1
    update performance_schema.threads 
    set INSTRUMENTED='NO' ,HISTORY='NO' where thread_id != 93315;
    

    performance_schema的相关统计信息表中可能会留有之前的统计信息,清空他们,以免造成干扰。

    # 会话1
    truncate performance_schema.events_stages_current;
    truncate performance_schema.events_stages_history;
    truncate performance_schema.events_stages_history_long;
    

    此时,我们在会话2中执行一条DML语句,测试一下

    # 会话2
    select count(*) from sbtest.sbtest4 where id between 100 and 1000;
    

    在会话1中,查询event_stages_history_long表,,加上where thead_id ='93315'(博主也不熟练,有时候感觉其他线程的信息还是在,加上防止意外)。
    通过查询结果,可以详细的看到一条select语句执行到的全过程以及每个过程的时间开销

    # 会话1
    select 
    THREAD_ID,
    EVENT_NAME,
    SOURCE,
    sys.format_time(TIMER_WAIT) as exec_time,
    WORK_COMPLETED,
    WORK_ESTIMATED 
    from performance_schema.events_stages_history_long
    where thread_id='93315';
    
    +-----------+--------------------------------+--------+-----------+----------------+----------------+
    | THREAD_ID | EVENT_NAME                     | SOURCE | exec_time | WORK_COMPLETED | WORK_ESTIMATED |
    +-----------+--------------------------------+--------+-----------+----------------+----------------+
    |     93315 | stage/sql/starting             |        | 591.62 us |           NULL |           NULL |
    |     93315 | stage/sql/checking permissions |        | 23.06 us  |           NULL |           NULL |
    |     93315 | stage/sql/Opening tables       |        | 128.12 us |           NULL |           NULL |
    |     93315 | stage/sql/init                 |        | 47.36 us  |           NULL |           NULL |
    |     93315 | stage/sql/System lock          |        | 22.02 us  |           NULL |           NULL |
    |     93315 | stage/sql/optimizing           |        | 15.71 us  |           NULL |           NULL |
    |     93315 | stage/sql/statistics           |        | 343.52 us |           NULL |           NULL |
    |     93315 | stage/sql/preparing            |        | 17.64 us  |           NULL |           NULL |
    |     93315 | stage/sql/executing            |        | 5.65 us   |           NULL |           NULL |
    |     93315 | stage/sql/Sending data         |        | 909.67 us |           NULL |           NULL |
    |     93315 | stage/sql/end                  |        | 2.11 us   |           NULL |           NULL |
    |     93315 | stage/sql/query end            |        | 23.36 us  |           NULL |           NULL |
    |     93315 | stage/sql/closing tables       |        | 12.85 us  |           NULL |           NULL |
    |     93315 | stage/sql/freeing items        |        | 47.46 us  |           NULL |           NULL |
    |     93315 | stage/sql/cleaning up          |        | 1.53 us   |           NULL |           NULL |
    +-----------+--------------------------------+--------+-----------+----------------+----------------+
    

    我们再试试DDL语句,先将信息再次清空

    # 会话1
    truncate performance_schema.events_stages_current;
    truncate performance_schema.events_stages_history;
    truncate performance_schema.events_stages_history_long;
    

    我们给某张表加一个索引,表数据量比较大,应该需要执行一段时间

    # 会话2
    alter table sbtest.sbtest1 add index i_c(c);
    

    我们在会话1再次查看他的阶段信息

    查询结果中,最后两列WORK_COMPLETEDWORK_ESTIMATED不为NULL,表示这个阶段事件是可以度量的事件,也就是可以看执行进度。

    加上order by TIMER_WAIT desc条件后,可以发现stage/innodb/alter table (insert)阶段,花费时间最长,可以对此进行优化。(还不会,明天研究一下!)

    # 会话1
    select 
    THREAD_ID,
    EVENT_NAME,
    SOURCE,
    sys.format_time(TIMER_WAIT) as exec_time,
    WORK_COMPLETED,
    WORK_ESTIMATED 
    from performance_schema.events_stages_history_long
    where thread_id='93315';
    
    +-----------+----------------------------------------------------+--------+-----------+----------------+----------------+
    | THREAD_ID | EVENT_NAME                                         | SOURCE | exec_time | WORK_COMPLETED | WORK_ESTIMATED |
    +-----------+----------------------------------------------------+--------+-----------+----------------+----------------+
    |     93315 | stage/innodb/alter table (merge sort)              |        | 3.28 m    |        2054799 |        3061693 |
    |     93315 | stage/innodb/alter table (insert)                  |        | 50.35 s   |        2744982 |        2746811 |
    |     93315 | stage/innodb/alter table (flush)                   |        | 3.27 s    |        2752061 |        2752061 |
    |     93315 | stage/innodb/alter table (log apply index)         |        | 6.55 ms   |        2752445 |        3082198 |
    |     93315 | stage/innodb/alter table (flush)                   |        | 67.68 us  |        2752445 |        3082198 |
    |     93315 | stage/sql/committing alter table to storage engine |        | 13.03 us  |           NULL |           NULL |
    |     93315 | stage/innodb/alter table (end)                     |        | 70.82 ms  |        3082198 |        3082198 |
    |     93315 | stage/sql/end                                      |        | 204.45 us |           NULL |           NULL |
    |     93315 | stage/sql/query end                                |        | 1.77 ms   |           NULL |           NULL |
    |     93315 | stage/sql/closing tables                           |        | 32.98 us  |           NULL |           NULL |
    |     93315 | stage/sql/freeing items                            |        | 91.17 us  |           NULL |           NULL |
    |     93315 | stage/sql/cleaning up                              |        | 1.86 us   |           NULL |           NULL |
    +-----------+----------------------------------------------------+--------+-----------+----------------+----------------+
    

    如果想看上方的加索引的语句,在执行时(也就是我们等待时),执行进度怎么办?可以通过sys.session表进行查看,如下

    # 会话 1
    # 如果sys.session 表中的 trx_state字段==null,表示没有performance_schema没有开启对事物状态信息的收集,此时需要开启对performance_schema事务状态信息的收集如下:
    update performance_schema.setup_instruments set ENABLEd='YES',TIMED='YES' where name = 'transaction';
    update performance_schema.setup_consumers set ENABLED='YES' where NAME='events_transactions_current';
    
    # 会话 2,在执行一个增加索引的语句进行测试
    alter table sbtest.sbtest1 add index i_k(k);
    
    # 会话 1
    # 查看当前正在执行的语句进度信息,会话2的conn_id=93290(它的thread_id=93315,可以用sys.ps_thread_id()函数进行转换)
    select * from sys.session where conn_id = '93290' and trx_state='ACTIVE'G;
    *************************** 1. row ***************************
                    thd_id: 93315
                   conn_id: 93290
                      user: root@localhost
                        db: performance_schema
                   command: Query
                     state: alter table (read PK and internal sort)
                      time: 13
         current_statement: alter table sbtest.sbtest1 add index i_k(k)
         statement_latency: 13.23 s
                  progress: 8.23   ## 进度!!!,到100就表示完成啦!
              lock_latency: 2.92 ms
             rows_examined: 0
                 rows_sent: 0
             rows_affected: 0
                tmp_tables: 0
           tmp_disk_tables: 0
                 full_scan: NO
            last_statement: NULL
    last_statement_latency: NULL
            current_memory: 0 bytes
                 last_wait: wait/io/file/innodb/innodb_data_file
         last_wait_latency: Still Waiting
                    source: 
               trx_latency: 13.40 s
                 trx_state: ACTIVE
            trx_autocommit: YES
                       pid: 20611
              program_name: mysql
    1 row in set (0.19 sec)
    
    # 补充:查看当前事务信息
    select * from information_schema.innodb_trxG;
    

    -----------------2020-10-28补充
    博主在检测一些查询时间较长的SQL时,此方法返回的时间不完整,只记录了一部分阶段的消耗时间,目前还没找到解决方法

  • 相关阅读:
    RabbitMQ source was instantiated with usesCorrelationId set to true but a message was received with correlation id set to null
    【Ubuntu】运行命令如何免输入YES和回车?
    运营的本质
    什么???前端页面统计停留时间你不会???那可得好好看看这个文章了
    使用el-switch实现开关(更改状态后展示状态)
    Linux编译安装时常见错误解决办法
    SignalR前后端通信
    声音类型识别库运行环境搭建
    uniapp使用axios(亲测可用)
    background + gradient 使用技巧
  • 原文地址:https://www.cnblogs.com/dbsqler/p/13850503.html
Copyright © 2011-2022 走看看