千金良方:MySQL性能优化金字塔法则
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

9.1 查看慢SQL语句慢在哪里

如果我们频繁地在慢查询日志中发现某个语句执行缓慢,且在表结构、索引结构、统计信息中都无法找出原因时,则可以利用sys系统库中的撒手锏:sys.session视图结合performance_schema的等待事件来找出症结所在。那么session视图有什么用呢?使用它可以查看当前用户会话的进程列表信息,数据来源于sys.processlist视图(使用该视图可以查询所有前台和后台线程的状态信息,默认按照进程等待时间和最近一条语句执行完成的时间降序排列。数据来源:performance_schema的threads、events_waits_current、events_statements_current、events_stages_current、events_transactions_current、session_connect_attrs等表和sys.x$memory_by_thread_by_current_bytes视图),查询结果字段与processlist视图类似,但session视图过滤掉了后台线程,只显示与前台(用户)线程相关的统计数据。该视图在MySQL 5.7.9中是新增的。

下面是使用session视图查询的结果集。

# 首先需要启用与等待事件相关的instrumentsconsumers,否则last_wait字段值可能为NULL
mysql> call sys.ps_setup_enable_instrument('wait');
+-------------------------+
| summary                  |
+-------------------------+
| Enabled 315 instruments |
+-------------------------+
1 row in set(0.02 sec)
Query OK, 0 rows affected(0.02 sec)
mysql> call sys.ps_setup_enable_consumer('wait');
+---------------------+
| summary             |
+---------------------+
| Enabled 3 consumers |
+---------------------+
1 row in set(0.00 sec)
Query OK, 0 rows affected(0.00 sec)
# 然后,使用session视图进行查询(这里只查询commandquery的线程信息,代表正在执行查询)
mysql> select * from session where command='query' and conn_id! =connection_id()\G
*************************** 1. row ***************************
                thd_id: 48          # 内部线程ID
              conn_id: 6            # 连接ID,即processlist_id
                  user:admin@localhost  # 对于前台线程,该字段值为account名称;对于后台线程,该字段值为后台线程名称
                  db: xiaoboluo   # 线程的默认数据库,如果没有默认数据库,则该字段值为NULL
              command: Query       # 对于前台线程,表示线程正在执行的客户端代码对应的命令类型,如果会话处于空闲状态,则该字段值为’Sleep';对于后台超线程,该字段值为NULL
                state: Sending data# 表示线程正在做什么:什么事件或状态,与processlist表中的state字段值一样
                  time: 72          # 表示线程处于当前状态已经持续了多长时间)
    current_statement: select * from test limit 1 for update # 线程当前正在执行的语句,如果没有执行任何语句,该字段值为NULL
    statement_latency: 1.20 m      # 线程当前语句已经执行了多长时间。该字段是MySQL 5.7.9中新增的
              progress: NULL       # 在支持进度报告的阶段事件中统计的工作进度百分比。该字段是MySQL 5.7.9中新增的
          lock_latency: 169.00 us  # 当前语句的锁等待时间
        rows_examined: 0           # 当前语句从存储引擎读取的数据行数
            rows_sent: 0           # 当前语句返回给客户端的数据行数
        rows_affected: 0           # 受当前语句影响的数据行数(DML语句对数据执行变更才会影响行)
            tmp_tables: 0          # 当前语句创建的内部内存临时表的数量
      tmp_disk_tables: 0           # 当前语句创建的内部磁盘临时表的数量
            full_scan: NO          # 当前语句执行的全表扫描次数
        last_statement: NULL       # 如果在 threads 表中没有找到正在执行的语句或正在等待执行的语句,那么在该字段可以显示线程执行的最后一条语句 events_statements_current 表中查找,该表会为每一个线程保留最后一条语句执行的事件信息,其他有current后缀的事件记录表也类似)
last_statement_latency: NULL      # 线程执行的最后一条语句执行了多长时间
        current_memory: 461 bytes  # 当前线程分配的字节数
            last_wait: wait/io/table/sql/handler  # 线程最近的等待事件的等待时间执行时间,从这里可以看到,当前正在等待表级别的I/O
    last_wait_latency: Still Waiting   # 线程最近的等待事件的等待时间执行时间)
                source: handler.cc:3185 # 线程最近的等待事件检测代码的源文件和行号
          trx_latency: NULL             # 线程当前正在执行的事务已经执行了多长时间。该字段是MySQL 5.7.9中新增的
            trx_state: NULL             # 线程当前正在执行的事务的状态。该字段是 MySQL 5.7.9中新增的
        trx_autocommit: NULL  # 线程当前正在执行的事务的提交模式,有效值为:'ACTIVE''COMMITTED''ROLLED BACK'。该字段是MySQL 5.7.9中新增的
                  pid: 3788    # 客户端进程ID。该字段是MySQL 5.7.9中新增的
          program_name: mysql # 客户端程序名称。该字段是MySQL 5.7.9中新增的
1 row in set(0.15 sec)