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视图查询的结果集。
#首先需要启用与等待事件相关的instruments和consumers,否则last_wait字段值可能为null mysql> call sys.ps_setup_enable_instrument('wait'); +-------------------------+ | summary | +-------------------------+ | Enabled 315 instruments | +-------------------------+ 1 row in set (0.01 sec) Query OK, 0 rows affected (0.01 sec) mysql> 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) mysql>
然后,使用session视图进行查询(这里只查询command为Sleep的线程信息)
mysql> select * from sys.session where command = 'Sleep' and conn_id != connection_id()G *************************** 1. row *************************** thd_id: 119491 #内部线程ID conn_id: 119466 #连接ID,即processlist_id user: user@10.2.13.88 #对于前台线程,该字段值为account名称;对于后台线程,该字段值为后台线程名称 db: NULL #线程的默认数据库,如果没有默认数据库,则该字段值为null command: Sleep #对于前台线程,表示线程正在执行的客户端代码对应的命令类型,如果会话处于空闲状态,则该字段值为sleep;对于后台线程,该字段值为null state: NULL #表示线程正在做什么,什么事件或状态,与processlist表中的state字段值一样 time: 46 #表示线程处于当前状态已经持续了多长时间(秒) current_statement: SHOW INDEX FROM `windranger_auth`.`sys_user` #线程当前正在执行的语句,如果没有执行任何语句,该字段值为null statement_latency: NULL #线程当前语句已经执行了多长时间,该字段是MySQL5.7.9中新增的 progress: NULL #在支持进度报告的阶段事件中统计的工作进度百分比,该字段是MySQL5.7.9中新增的 lock_latency: 198.00 us #当前语句的锁等待时间 rows_examined: 2 #当前语句从存储引擎读取的数据行数 rows_sent: 2 #当前语句返回给客户端的数据行数 rows_affected: 0 #受当前语句影响的数据行数(DML语句对数据执行变更才会影响行) tmp_tables: 1 #当前语句创建的内部内存临时表的数量 tmp_disk_tables: 0 #当前语句创建的内部磁盘临时表的数量 full_scan: YES #当前语句是否执行全表扫描 last_statement: SHOW INDEX FROM `windranger_auth`.`sys_user` #如果在threads表中没有找到正在执行的语句或正在在等待执行的语句,那么该字段可以显示线程执行的最后一天语句(在performance_schema.events_waits_current表中查找,该表会为每一个线程保留最后一条语句执行的事件信息,其他有current后缀的事件记录表也类似) last_statement_latency: 430.20 us #线程执行的最后一条语句执行了多长时间 current_memory: 0 bytes #当前线程分配的字节数 last_wait: idle #线程最近的等待事件的等待时间(执行时间),从这里可以看到,当前处于空闲状态 last_wait_latency: Still Waiting #线程最近的等待事件的等待时间(执行时间) source: #线程最近的等待事件检测代码的源文件和行号 trx_latency: NULL #线程当前正在执行的事物已经执行了多长时间,该字段是MySQL5.7.9中新增的 trx_state: NULL #线程当前正在执行的事物的状态,该字段是MySQL5.7.9中新增的 trx_autocommit: NULL #线程当前正在执行的事物的提交模式,有效值为:ACTIVE,COMMITTED,ROLLED BACK ,该字段是MySQL5.7.9中新增的 pid: 19000 # 客户端进程id,该字段是MySQL5.7.9中新增的 program_name: MySQLWorkbench #客户端程序名称,该字段是MySQL5.7.9中新增的
2.查看是否有事务锁等待
通过innodb_lock_waits视图可以查看InnoDB当前事务锁等待信息,默认按照发生锁等待的开始时间升序排列——wait_started字段即innodb_trx表的trx_wait_started字段。数据来源:information_schema下的innodb_trx、innodb_locks、innodb_lock_waits表(注:在MySQL 8.0及之后的版本中,该视图的信息来源为information_schema下的innodb_trx表、performance_schema下的data_locks表和data_lock_waits表)。下面是使用innodb_lock_waits视图查询的结果集。
mysql> select * from sys.innodb_lock_waitsG *************************** 1. row *************************** wait_started: 2020-09-16 11:21:42 #发生锁等待的开始时间 wait_age: 00:00:06 #锁已经等待了多久,该值是一个时间格式值 wait_age_secs: 6 #锁已经等待了几秒钟,该值是一个整型值,该字段是MySQL5.7.9中新增的 locked_table: `employees`.`dept_emp` #锁等待的表名称 locked_index: PRIMARY #锁等待的索引名称 locked_type: RECORD #锁等待的锁类型 waiting_trx_id: 8325 #锁等待的事物ID waiting_trx_started: 2020-09-16 11:21:42 #发生锁等待的事务开始时间 waiting_trx_age: 00:00:06 #发生锁等待的事务总的锁等待时间,该值是一个时间格式 waiting_trx_rows_locked: 1 #发生锁等待的事务已经锁定的行数(如果是复杂事务会累计) waiting_trx_rows_modified: 0 #发生锁等待的事务已经修改的行数(如果是复杂事务会累计) waiting_pid: 128861 #发生锁等待的事务的processlist_id waiting_query: update employees.dept_emp set ... 99-01-02' where emp_no='10001' #发生锁等待的事务的SQL语句文本 waiting_lock_id: 8325:60:6:2 #发生锁等待的锁id waiting_lock_mode: X #发生锁等待的锁模式 blocking_trx_id: 8324 #持有锁的事务id blocking_pid: 128819 #持有锁的事务的processlist_id blocking_query: NULL #持有锁的事务的SQL语句文本 blocking_lock_id: 8324:60:6:2 #持有锁的锁id blocking_lock_mode: X #持有锁的锁模式 blocking_trx_started: 2020-09-16 11:20:53 #持有锁的事务的开始时间 blocking_trx_age: 00:00:55 #持有锁的事务已执行了多长时间,该值为时间格式值 blocking_trx_rows_locked: 332334 #持有锁的事务的锁定行数 blocking_trx_rows_modified: 0 #持有锁的事务需要修改的行数 sql_kill_blocking_query: KILL QUERY 128819 #执行KILL语句来杀死持有锁的查询语句(而不是终止会话)。该字段是MySQL5.7.9中新增的 sql_kill_blocking_connection: KILL 128819 #执行KILL语句以终止持有锁的语句的会话。该字段是MySQL5.7.9中新增的 1 row in set, 3 warnings (0.17 sec) mysql>
下面贴出视图查询语句文本。
show create views sys.innodb_lock_waits;
CREATE VIEW sys.innodb_lock_waits AS select r.trx_wait_started AS wait_started, timediff(now(), r.trx_wait_started) AS wait_age, timestampdiff(SECOND, r.trx_wait_started, now()) AS wait_age_secs, rl.lock_table AS locked_table, rl.lock_index AS locked_index, rl.lock_type AS locked_type, r.trx_id AS waiting_trx_id, r.trx_started AS waiting_trx_started, timediff(now(), r.trx_started) AS waiting_trx_age, r.trx_rows_locked AS waiting_trx_rows_locked, r.trx_rows_modified AS waiting_trx_rows_modified, r.trx_mysql_thread_id AS waiting_pid, sys.format_statement(r.trx_query) AS waiting_query, rl.lock_id AS waiting_lock_id, rl.lock_mode AS waiting_lock_mode, b.trx_id AS blocking_trx_id, b.trx_mysql_thread_id AS blocking_pid, sys.format_statement(b.trx_query) AS blocking_query, bl.lock_id AS blocking_lock_id, bl.lock_mode AS blocking_lock_mode, b.trx_started AS blocking_trx_started, timediff(now(), b.trx_started) AS blocking_trx_age, b.trx_rows_locked AS blocking_trx_rows_locked, b.trx_rows_modified AS blocking_trx_rows_modified, concat('KILL QUERY ', b.trx_mysql_thread_id) AS sql_kill_blocking_query, concat('KILL ', b.trx_mysql_thread_id) AS sql_kill_blocking_connection from ((((information_schema.innodb_lock_waits w join information_schema.innodb_trx b on((b.trx_id = w.blocking_trx_id))) join information_schema.innodb_trx r on((r.trx_id = w.requesting_trx_id))) join information_schema.innodb_locks bl on((bl.lock_id = w.blocking_lock_id))) join information_schema.innodb_locks rl on((rl.lock_id = w.requested_lock_id))) order by r.trx_wait_started
3.查看是否有MDL锁等待
通过schema_table_lock_waits视图可以查看当前链接线程的MDL锁等待信息,显示哪些会话被MDL锁阻塞,是谁阻塞了这些会话,数据来源:performance_schema下的threads、metadata_locks、events_statements_current表。该视图是MySQL 5.7.9中新增的。下面是使用schema_table_lock_waits视图查询的结果集。
首先需要启用与MDL锁等待时间相关的instruments
mysql> call sys.ps_setup_enable_instrument('wait/lock/metadata/sql/mdl'); +-----------------------+ | summary | +-----------------------+ | Enabled 0 instruments | +-----------------------+ 1 row in set (0.00 sec) Query OK, 0 rows affected (0.00 sec) mysql>
然后,使用innodb_lock_waits视图进行查询(注意:请自行模拟一个事物不提交,一个事务执行ddl操作的场景,即可查询到类似如下的MDL锁等待信息)
mysql> select * from sys.schema_table_lock_waitsG *************************** 1. row *************************** object_schema: employees #发生MDL锁等待的schema名称 object_name: dept_emp #正在等待MDL锁的表名称 waiting_thread_id: 130764 #正在等待MDL锁的线程ID waiting_pid: 130739 #正在等待MDL锁的processlist_id waiting_account: root@localhost #正在等待MDL锁与线程关联的account名称 waiting_lock_type: EXCLUSIVE #被阻塞的线程正在等待的MDL锁类型 waiting_lock_duration: TRANSACTION #该字段来自元数据锁子系统中的锁定时间,有效值为:STATEMENT、TRANSACTION、EXPLICIT、STATMENT和TRANSACTION值分别表示在语句或事务结束时会释放的锁。EXPLICIT值表示可以在语句或事务结束时会被保留,需要显示释放的锁,例如:使用FLUSH TABLES WITH READ LOCK获取的全局锁 waiting_query: ALTER TABLE `employees`.`dept_ ... te` DATE NOT NULL COMMENT '时间' #正在等待MDL锁的线程对应的语句文本 waiting_query_secs: 7 #正在等待MDL锁的语句已经等待了多长时间(秒) waiting_query_rows_affected: 0 #受正在等待MDL锁的语句影响的数据行数(该字段来自performance_schema.events_statement_current表,该表中记录的是语句事件,如果语句是多表联结查询语句,则该语句可能已经执行了一部分DML语句,所以即使改语句当前被其他线程阻塞了,被阻塞线程的这个字段也可能出现大于0的值) waiting_query_rows_examined: 0 #正在等待MDL锁的语句从存储引擎检查的数据行数(同理,该字段来自performance_schema.events_statement_current) blocking_thread_id: 130763 #持有MDL锁的线程id blocking_pid: 130738 #持有MDL锁的processlist_id blocking_account: root@localhost #持有MDL锁的与线程关联的account名称 blocking_lock_type: SHARED_WRITE #持有MDL锁的锁类型 blocking_lock_duration: TRANSACTION #与waiting_lock_duration字段的解释相同,只是该值与持有MDL锁的线程相关 sql_kill_blocking_query: KILL QUERY 130738 #生成的KILL持有MDL锁的查询语句 sql_kill_blocking_connection: KILL 130738 #生成的KILL持有MDL锁的对应会话的语句 *************************** 2. row *************************** object_schema: employees object_name: dept_emp waiting_thread_id: 130764 waiting_pid: 130739 waiting_account: root@localhost waiting_lock_type: EXCLUSIVE waiting_lock_duration: TRANSACTION waiting_query: ALTER TABLE `employees`.`dept_ ... te` DATE NOT NULL COMMENT '时间' waiting_query_secs: 7 waiting_query_rows_affected: 0 waiting_query_rows_examined: 0 blocking_thread_id: 130764 blocking_pid: 130739 blocking_account: root@localhost blocking_lock_type: SHARED_UPGRADABLE blocking_lock_duration: TRANSACTION sql_kill_blocking_query: KILL QUERY 130739 sql_kill_blocking_connection: KILL 130739 2 rows in set (0.06 sec) mysql>
下面贴出视图查询语句文本。
CREATE VIEW sys.schema_table_lock_waits AS select g.OBJECT_SCHEMA AS object_schema, g.OBJECT_NAME AS object_name, pt.THREAD_ID AS waiting_thread_id, pt.PROCESSLIST_ID AS waiting_pid, sys.ps_thread_account(p.OWNER_THREAD_ID) AS waiting_account, p.LOCK_TYPE AS waiting_lock_type, p.LOCK_DURATION AS waiting_lock_duration, sys.format_statement(pt.PROCESSLIST_INFO) AS waiting_query, pt.PROCESSLIST_TIME AS waiting_query_secs, ps.ROWS_AFFECTED AS waiting_query_rows_affected, ps.ROWS_EXAMINED AS waiting_query_rows_examined, gt.THREAD_ID AS blocking_thread_id, gt.PROCESSLIST_ID AS blocking_pid, sys.ps_thread_account(g.OWNER_THREAD_ID) AS blocking_account, g.LOCK_TYPE AS blocking_lock_type, g.LOCK_DURATION AS blocking_lock_duration, concat('KILL QUERY ', gt.PROCESSLIST_ID) AS sql_kill_blocking_query, concat('KILL ', gt.PROCESSLIST_ID) AS sql_kill_blocking_connection from (((((performance_schema.metadata_locks g join performance_schema.metadata_locks p on(((g.OBJECT_TYPE = p.OBJECT_TYPE) and (g.OBJECT_SCHEMA = p.OBJECT_SCHEMA) and (g.OBJECT_NAME = p.OBJECT_NAME) and (g.LOCK_STATUS = 'GRANTED') and (p.LOCK_STATUS = 'PENDING')))) join performance_schema.threads gt on((g.OWNER_THREAD_ID = gt.THREAD_ID))) join performance_schema.threads pt on((p.OWNER_THREAD_ID = pt.THREAD_ID))) left join performance_schema.events_statements_current gs on((g.OWNER_THREAD_ID = gs.THREAD_ID))) left join performance_schema.events_statements_current ps on((p.OWNER_THREAD_ID = ps.THREAD_ID))) where (g.OBJECT_TYPE = 'TABLE')
4.查看InnoDB缓冲池中的热点数据有哪些
使用innodb_buffer_stats_by_schema视图可以按照schema分组查询InnoDB缓冲池的统计信息,默认按照已分配的buffer size(缓冲区大小)降序排列(allocated字段)。数据来源:information_schema.innodb_buffer_page。下面是使用innodb_buffer_stats_by_schema视图查询的结果集。
mysql> select * from sys.innodb_buffer_stats_by_schema; +--------------------------+------------+------------+-------+--------------+-----------+-------------+ | object_schema | allocated | data | pages | pages_hashed | pages_old | rows_cached | +--------------------------+------------+------------+-------+--------------+-----------+-------------+ | employees | 200.22 MiB | 185.39 MiB | 12814 | 0 | 4116 | 1636491 | | windranger_foundation | 1.41 MiB | 75.19 KiB | 90 | 0 | 90 | 20 | | windranger_emr | 1.30 MiB | 0 bytes | 83 | 0 | 31 | 0 | | clis | 1.27 MiB | 32.36 KiB | 81 | 0 | 81 | 17 | | InnoDB System | 656.00 KiB | 328.10 KiB | 41 | 15 | 41 | 858 | | windranger_pharmaux | 528.00 KiB | 14.81 KiB | 33 | 0 | 33 | 16 | | windranger_hospital | 464.00 KiB | 3.24 KiB | 29 | 0 | 14 | 6 | | mysql | 416.00 KiB | 182.37 KiB | 26 | 15 | 26 | 1710 | | windranger_coms | 384.00 KiB | 0 bytes | 24 | 0 | 24 | 0 | | windranger_auth | 352.00 KiB | 29.75 KiB | 22 | 0 | 22 | 50 | | windranger_ifm | 288.00 KiB | 0 bytes | 18 | 0 | 18 | 0 | | windranger_sync | 288.00 KiB | 87.01 KiB | 18 | 0 | 17 | 228 | | windranger_smartward | 240.00 KiB | 136 bytes | 15 | 0 | 15 | 1 | | windranger_qm | 176.00 KiB | 0 bytes | 11 | 0 | 11 | 0 | | test_cipher | 32.00 KiB | 144 bytes | 2 | 0 | 1 | 1 | | windranger_consumableaux | 32.00 KiB | 0 bytes | 2 | 0 | 2 | 0 | | demo_ds | 16.00 KiB | 251 bytes | 1 | 0 | 0 | 3 | | sys | 16.00 KiB | 279 bytes | 1 | 0 | 0 | 5 | +--------------------------+------------+------------+-------+--------------+-----------+-------------+ 18 rows in set (0.27 sec)
allocated: 已分配的大小
data: 总共分配的大小
pages: 分配的页面总数。
pages_hashed:分配的哈希页面总数。
pages_old:分配的旧页面总数。
rows_cached:高速缓存行总数。
下面贴出视图查询语句文本。
CREATE VIEW sys.innodb_buffer_stats_by_schema AS select if((locate('.', ibp.TABLE_NAME) = 0), 'InnoDB System', replace(substring_index(ibp.TABLE_NAME, '.', 1), '', '')) AS object_schema, sys.format_bytes(sum(if((ibp.COMPRESSED_SIZE = 0), 16384, ibp.COMPRESSED_SIZE))) AS allocated, sys.format_bytes(sum(ibp.DATA_SIZE)) AS data, count(ibp.PAGE_NUMBER) AS pages, count(if((ibp.IS_HASHED = 'YES'), 1, NULL)) AS pages_hashed, count(if((ibp.IS_OLD = 'YES'), 1, NULL)) AS pages_old, round((sum(ibp.NUMBER_RECORDS) / count(distinct ibp.INDEX_NAME)), 0) AS rows_cached from information_schema.innodb_buffer_page ibp where (ibp.TABLE_NAME is not null) group by object_schema order by sum(if((ibp.COMPRESSED_SIZE = 0), 16384, ibp.COMPRESSED_SIZE)) desc
5.查看冗余索引
使用schema_redundant_indexes视图可以查看重复或冗余索引,数据来源: sys.x$schema_flattened_keys 该数据来源视图被称作schema_redundant_indexes视图的辅助视图。schema_redundant_indexes视图是MySQL 5.7.9中新增的。下面是使用schema_redundant_indexes视图查询的结果集。
mysql> select * from sys.schema_redundant_indexesG *************************** 1. row *************************** table_schema: employees #包含重复或冗余索引的表对应的schema名称 table_name: dept_emp #包含重复或冗余索引的表名 redundant_index_name: emp_no #包含重复或冗余索引的名称 redundant_index_columns: emp_no #包含重复或冗余索引的列名 redundant_index_non_unique: 1 #重复或冗余索引中非唯一列的数量 dominant_index_name: PRIMARY #与重复或冗余索引相比占据优势(最佳)的索引名称 dominant_index_columns: emp_no,dept_no #占据优势(最佳)的索引中的列名 dominant_index_non_unique: 0 #占据优势(最佳)的索引中非唯一列的数量 subpart_exists: 0 #重复或冗余索引是否是前缀索引 sql_drop_index: ALTER TABLE `employees`.`dept_emp` DROP INDEX `emp_no` #针对重复或冗余索引生成的drop index语句
6.查看未使用的索引
使用schema_unused_indexes视图可以查看不活跃的索引(没有任何事件发生的索引,表示该索引从未使用过),在默认情况下按照schema名称和表名进行排序。数据来源:performance_schema.table_io_waits_summary_by_index_usage,该视图在服务器启动并运行足够长的时间后,所查询出的数据才比较实用;否则,使用该视图查询出的数据可能并不十分可靠,因为统计的数据可能并不精确,有一部分业务查询逻辑可能还来不及查询。下面是使用schema_unused_indexes视图查询的结果集。
mysql> select * from sys.schema_unused_indexes; +-----------------+-------------------------+----------------------+ | object_schema | object_name | index_name | +-----------------+-------------------------+----------------------+ | aa | test | idx_test_1 | | employees | dept_emp | emp_no | | employees | dept_emp | dept_no | | employees | dept_manager | dept_no | | employees | dept_manager | emp_no | | employees | salaries | emp_no | | employees | titles | emp_no | | mongo_slowsql | mongo_slow_query_review | IX_i_d_p | | mongo_slowsql | mongo_status_info | IX_tag | | testdb | test_deadlock | b | | testdb | test_stat | idx_test_stat_1 | +-----------------+-------------------------+----------------------+ 12 rows in set (0.04 sec) mysql>
下面贴出视图查询语句文本。
CREATE VIEW schema_unused_indexes AS select t.OBJECT_SCHEMA AS object_schema, t.OBJECT_NAME AS object_name, t.INDEX_NAME AS index_name from (performance_schema.table_io_waits_summary_by_index_usage t join information_schema.statistics s on(((t.OBJECT_SCHEMA = s.TABLE_SCHEMA) and (t.OBJECT_NAME = s.TABLE_NAME) and (t.INDEX_NAME = s.INDEX_NAME)))) where ((t.INDEX_NAME is not null) and (t.COUNT_STAR = 0) and (t.OBJECT_SCHEMA <> 'mysql') and (t.INDEX_NAME <> 'PRIMARY') and (s.NON_UNIQUE = 1) and (s.SEQ_IN_INDEX = 1)) order by t.OBJECT_SCHEMA, t.OBJECT_NAME
7.查询表的增、删、改、查数据量和I/O耗时统计信息
使用schema_table_statistics_with_buffer视图可以查询表的增、删、改、查数据量,I/O耗时,以及在InnoDB缓冲池中占用情况等统计信息,在默认情况下按照增、删、改、查操作的总表I/O延迟时间(执行时间,也可以理解为存在最多I/O争用的表)降序排列。数据来源:performance_schema.table_io_waits_summary_by_table、 sys.x$ps_schema_table_statistics_io 、 sys.x$innodb_buffer_stats_by_table 。另外,该视图在内部使用了辅助视图 sys.x$ps_schema_table_statistics_io 。下面是使用schema_table_statistics_with_buffer视图查询的结果集(请自行创建库表,并执行一些DML语句进行造数)。
mysql> select * from sys.schema_table_statistics_with_buffer limit 1G *************************** 1. row *************************** table_schema: employees #包含table_name字段的表所在的schema名称 table_name: dept_emp #表名 rows_fetched: 332606 #表读取操作的总数据行数,针对表查询操作 fetch_latency: 52.03 s #表select操作的I/O事件的总延迟时间(执行时间),针对表查询操作 rows_inserted: 0 #表插入操作的总数据行数,针对表插入操作 insert_latency: 0 ps #表insert操作的I/O事件的总延迟时间(执行时间),针对表插入操作 rows_updated: 0 #表更新操作的总数据行数,针对表更新操作 update_latency: 0 ps #表update操作的I/O事件的总延迟时间(执行时间),针对表更新操作 rows_deleted: 0 #表删除操作的总数据行数,针对表删除操作 delete_latency: 0 ps #表delete操作的I/O事件的总延迟时间(执行时间),针对表删除操作 io_read_requests: 761 #表读取操作的总请求次数,针对表.ibd和.frm文件的读I/O操作 io_read: 11.58 MiB #与表读操作相关的所有文件读取操作的总字节数,针对表.ibd和.frm文件的读I/O操作 io_read_latency: 288.42 ms #与表读操作相关的所有文件读取操作的总延迟时间(执行时间),针对表.ibd和.frm文件的读I/O操作 io_write_requests: 0 #表写操作的总请求次数,针对表.ibd和.frm文件的写I/O操作 io_write: 0 bytes #与表写操作相关的所有文件写操作的总字节数,针对表.ibd和.frm文件的写I/O操作 io_write_latency: 0 ps #与表写操作相关的所有文件写操作的总延迟时间(执行时间),针对表.ibd和.frm文件的写I/O操作 io_misc_requests: 24 #与表其他各种混杂操作相关的所有文件的I/O请求总次数,针对表.ibd和.frm文件的其他混杂的I/O操作 io_misc_latency: 501.30 us #与表其他各种混杂操作相关的所有文件的I/O请求的总延迟时间(执行时间),针对表.ibd和.frm文件的其他混杂的I/O操作 innodb_buffer_allocated: 11.47 MiB #当前已经分配给表的缓冲池总字节数 innodb_buffer_data: 10.46 MiB #当前已经分配给表的数据部分使用的缓冲池字节总数 innodb_buffer_free: 1.01 MiB #当前已经分配给表的非数据部分使用的缓冲池字节总数(即空闲页所在的字节数,计算公式:innodb_buffer_allocated - innodb_buffer_data) innodb_buffer_pages: 734 #当前已经分配给表的缓冲池总页数 innodb_buffer_pages_hashed: 0 #当前已经分配给表的自适应hash索引页总数 innodb_buffer_pages_old: 0 #当前已经分配给表的旧业总数(位于LRU列表中的旧块子列表中的页数) innodb_buffer_rows_cached: 166596 #在缓冲池中为表缓存的总数据行数(table_name字段显示的表在缓冲池中缓存了多少行数据) 1 row in set (0.20 sec) mysql>
8.查看MySQL磁盘文件产生的磁盘流量与读写比例
使用io_global_by_file_by_bytes视图可以按照文件路径+名称分组(磁盘文件名)查看全局的I/O读写字节数、读写文件I/O事件数量统计信息,在默认情况下按照总I/O读写字节数进行降序排列。数据来源:performance_schema.file_summary_by_instance。下面是使用io_global_by_file_by_bytes视图查询的结果集。
mysql> select * from sys.io_global_by_file_by_bytes limit 1G *************************** 1. row *************************** file: @@datadir/ibtmp1 #文件路径名 count_read: 0 #文件的读取事件总数。 total_read: 0 bytes #从文件读取的字节总数。 avg_read: 0 bytes #从文件中每次读取的平均字节数。 count_write: 6887 #文件的写事件总数。 total_written: 119.42 MiB #写入文件的总字节数。 avg_write: 17.76 KiB #每次写入文件的平均字节数。 total: 119.42 MiB #文件读取和写入的字节总数。 write_pct: 100.00 #写入的I/O的总字节数百分比。 1 row in set (0.00 sec) mysql>
9.查看哪些语句使用了全表扫描
使用statements_with_full_table_scans视图可以查看全表扫描或者没有使用最优索引的语句(经过标准化转换的语句文本),在默认情况下按照全表扫描次数与语句总次数百分比和语句总延迟时间(执行时间)降序排列。数据来源:performance_schema.events_statements_summary_by_digest。下面是使用statements_with_full_table_scans视图查询的结果集。
mysql> select * from sys.statements_with_full_table_scans limit 1G *************************** 1. row *************************** query: SELECT IF ( `isnull` ( `perfor ... AND ( `performance_schema` . #经过标准化转换的语句字符串 db: NULL #语句对应的默认数据库,如果没有默认数据库,则该字段值为null exec_count: 2 #语句执行的总次数 total_latency: 975.50 us #语句执行的总延迟时间(执行时间) no_index_used_count: 2 #语句执行没有使用索引扫描表(而是使用全表扫描)的总次数 no_good_index_used_count: 0 #语句执行没有使用更好的索引扫描表的总次数 no_index_used_pct: 100 #语句执行没有使用索引扫描表(而是使用全表扫描)的次数与语句执行总次数的百分比 rows_sent: 12 #语句执行从表返回给客户端的总数据行数 rows_examined: 12 #语句执行从存储引擎检查的总数据行数 rows_sent_avg: 6 #每条语句执行从表返回给客户端的平均数据行数 rows_examined_avg: 6 #每条语句执行从存储引擎读取的平均数据行数 first_seen: 2020-09-14 15:33:29 #该语句第一次出现的时间 last_seen: 2020-09-15 21:51:33 #该语句最近一次出现的时间 digest: 46dccd5285e08c22c1583a4218d02dbe #语句摘要计算的MD5 hash值 1 row in set (0.01 sec) mysql>
下面贴出视图查询语句文本。
CREATE VIEW statements_with_full_table_scans AS select sys.format_statement(performance_schema.events_statements_summary_by_digest.DIGEST_TEXT) AS query, performance_schema.events_statements_summary_by_digest.SCHEMA_NAME AS db, performance_schema.events_statements_summary_by_digest.COUNT_STAR AS exec_count, sys.format_time(performance_schema.events_statements_summary_by_digest.SUM_TIMER_WAIT) AS total_latency, performance_schema.events_statements_summary_by_digest.SUM_NO_INDEX_USED AS no_index_used_count, performance_schema.events_statements_summary_by_digest.SUM_NO_GOOD_INDEX_USED AS no_good_index_used_count, round((ifnull((performance_schema.events_statements_summary_by_digest.SUM_NO_INDEX_USED / nullif(performance_schema.events_statements_summary_by_digest.COUNT_STAR, 0)), 0) * 100), 0) AS no_index_used_pct, performance_schema.events_statements_summary_by_digest.SUM_ROWS_SENT AS rows_sent, performance_schema.events_statements_summary_by_digest.SUM_ROWS_EXAMINED AS rows_examined, round((performance_schema.events_statements_summary_by_digest.SUM_ROWS_SENT / performance_schema.events_statements_summary_by_digest.COUNT_STAR), 0) AS rows_sent_avg, round((performance_schema.events_statements_summary_by_digest.SUM_ROWS_EXAMINED / performance_schema.events_statements_summary_by_digest.COUNT_STAR), 0) AS rows_examined_avg, performance_schema.events_statements_summary_by_digest.FIRST_SEEN AS first_seen, performance_schema.events_statements_summary_by_digest.LAST_SEEN AS last_seen, performance_schema.events_statements_summary_by_digest.DIGEST AS digest from performance_schema.events_statements_summary_by_digest where (((performance_schema.events_statements_summary_by_digest.SUM_NO_INDEX_USED > 0) or (performance_schema.events_statements_summary_by_digest.SUM_NO_GOOD_INDEX_USED > 0)) and (not ((performance_schema.events_statements_summary_by_digest.DIGEST_TEXT like 'SHOW%')))) order by round((ifnull((performance_schema.events_statements_summary_by_digest.SUM_NO_INDEX_USED / nullif(performance_schema.events_statements_summary_by_digest.COUNT_STAR, 0)), 0) * 100), 0) desc, sys.format_time(performance_schema.events_statements_summary_by_digest.SUM_TIMER_WAIT) desc
11.查看哪些语句使用了文件排序
使用statements_with_sorting视图可以查看执行了文件排序的语句,在默认情况下按照语句总延迟时间(执行时间)降序排列。数据来源:
performance_schema.events_statements_ summary_by_digest。下面是使用statements_with_sorting视图查询的结果集。
mysql> select * from sys.statements_with_sortingG *************************** 1. row *************************** query: SELECT IF ( ( `locate` ( ? , ` ... . `COMPRESSED_SIZE` ) ) DESC #经过标准化转换的语句字符串 db: sys #语句对应的默认数据库,如果没有默认数据库,则该字段值为null exec_count: 52 #语句执行的总次数 total_latency: 825.71 ms #语句执行的总延迟时间(执行时间) sort_merge_passes: 22 #语句执行发生的语句排序合并的总次数 avg_sort_merges: 0 #针对发生排序合并的语句,每条语句的平均排序合并次数(见视图查询语句文本中的SUM_SORT_MERGE_PASSES/COUNT_STAR) sorts_using_scans: 8 #语句排序执行全表扫描的总次数 sort_using_range: 0 #语句排序执行范围扫描的总次数 rows_sorted: 28670 #语句执行发生排序的总数据行数 avg_rows_sorted: 551 #针对发生排序的语句,每条语句的平均排序数据行数(见视图查询语句文本中的SUM_SORT_ROWS/COUNT_STAR) first_seen: 2020-09-14 17:45:48 #该语句第一次出现的时间 last_seen: 2020-09-18 14:03:19 #该语句最近一次出现的时间 digest: 410a247bd55c869c709912d4cb6ec9c4 #语句摘要计算的MD5 hash值
下面贴出视图查询语句文本。
CREATE VIEW statements_with_sorting AS select sys.format_statement(performance_schema.events_statements_summary_by_digest.DIGEST_TEXT) AS query, performance_schema.events_statements_summary_by_digest.SCHEMA_NAME AS db, performance_schema.events_statements_summary_by_digest.COUNT_STAR AS exec_count, sys.format_time(performance_schema.events_statements_summary_by_digest.SUM_TIMER_WAIT) AS total_latency, performance_schema.events_statements_summary_by_digest.SUM_SORT_MERGE_PASSES AS sort_merge_passes, round(ifnull((performance_schema.events_statements_summary_by_digest.SUM_SORT_MERGE_PASSES / nullif(performance_schema.events_statements_summary_by_digest.COUNT_STAR, 0)), 0), 0) AS avg_sort_merges, performance_schema.events_statements_summary_by_digest.SUM_SORT_SCAN AS sorts_using_scans, performance_schema.events_statements_summary_by_digest.SUM_SORT_RANGE AS sort_using_range, performance_schema.events_statements_summary_by_digest.SUM_SORT_ROWS AS rows_sorted, round(ifnull((performance_schema.events_statements_summary_by_digest.SUM_SORT_ROWS / nullif(performance_schema.events_statements_summary_by_digest.COUNT_STAR, 0)), 0), 0) AS avg_rows_sorted, performance_schema.events_statements_summary_by_digest.FIRST_SEEN AS first_seen, performance_schema.events_statements_summary_by_digest.LAST_SEEN AS last_seen, performance_schema.events_statements_summary_by_digest.DIGEST AS digest from performance_schema.events_statements_summary_by_digest where (performance_schema.events_statements_summary_by_digest.SUM_SORT_ROWS > 0) order by performance_schema.events_statements_summary_by_digest.SUM_TIMER_WAIT desc
12.查看哪些语句使用了临时表
使用statements_with_temp_tables视图可以查看使用了临时表的语句,在默认情况下按照磁盘临时表数量和内存临时表数量进行降序排列。数据来源:performance_schema.events_ statements_summary_by_digest。下面是使用statements_with_temp_tables视图查询的结果集。
mysql> select * from sys.statements_with_temp_tables limit 1G *************************** 1. row *************************** query: SELECT IF ( ( `locate` ( ? , ` ... . `COMPRESSED_SIZE` ) ) DESC #经过标准化转换的语句字符串 db: sys #语句对应的默认数据库,如果没有默认数据库,则该字段值为null exec_count: 3 #语句执行的总次数 total_latency: 583.97 ms #语句执行的总延迟时间(执行时间) memory_tmp_tables: 24 #语句执行时创建的内部内存临时表的总数量 disk_tmp_tables: 15 #语句执行时创建的内部磁盘临时表的总数量 avg_tmp_tables_per_query: 8 #对于使用了内存临时表的语句,每条语句使用内存临时表的平均数量(见视图查询语句文本中的SUM_CREATED_TMP_TABLES/COUNT_STAR) tmp_tables_to_disk_pct: 63 #内存临时表的总数量与磁盘临时表的总数量百分比,表示磁盘临时表的转换率(见视图查询语句文本中的SUM_CREATED_TMP_DISK_TABLES/SUM_CREATED_TMP_TABLES) first_seen: 2020-09-18 13:19:55 #该语句第一次出现的时间 last_seen: 2020-09-18 14:03:59 #该语句最近一次出现的时间 digest: cdc49c85aa2a0790a8ac38cd6e117ff2 #语句摘要计算的MD5 hash值 1 row in set (0.01 sec) mysql>
下面贴出视图查询语句文本。
CREATE VIEW statements_with_temp_tables AS select sys.format_statement(performance_schema.events_statements_summary_by_digest.DIGEST_TEXT) AS query, performance_schema.events_statements_summary_by_digest.SCHEMA_NAME AS db, performance_schema.events_statements_summary_by_digest.COUNT_STAR AS exec_count, sys.format_time(performance_schema.events_statements_summary_by_digest.SUM_TIMER_WAIT) AS total_latency, performance_schema.events_statements_summary_by_digest.SUM_CREATED_TMP_TABLES AS memory_tmp_tables, performance_schema.events_statements_summary_by_digest.SUM_CREATED_TMP_DISK_TABLES AS disk_tmp_tables, round(ifnull((performance_schema.events_statements_summary_by_digest.SUM_CREATED_TMP_TABLES / nullif(performance_schema.events_statements_summary_by_digest.COUNT_STAR, 0)), 0), 0) AS avg_tmp_tables_per_query, round((ifnull((performance_schema.events_statements_summary_by_digest.SUM_CREATED_TMP_DISK_TABLES / nullif(performance_schema.events_statements_summary_by_digest.SUM_CREATED_TMP_TABLES, 0)), 0) * 100), 0) AS tmp_tables_to_disk_pct, performance_schema.events_statements_summary_by_digest.FIRST_SEEN AS first_seen, performance_schema.events_statements_summary_by_digest.LAST_SEEN AS last_seen, performance_schema.events_statements_summary_by_digest.DIGEST AS digest from performance_schema.events_statements_summary_by_digest where (performance_schema.events_statements_summary_by_digest.SUM_CREATED_TMP_TABLES > 0) order by performance_schema.events_statements_summary_by_digest.SUM_CREATED_TMP_DISK_TABLES desc, performance_schema.events_statements_summary_by_digest.SUM_CREATED_TMP_TABLES desc
温馨提示:关于sys系统库更详细的内容,可参阅微信公众号“沃趣技术”,其中我们用15个章节对其进行了全方位的介绍。