• Mysql高级——性能分析工具(2)


    6. 分析查询语句:EXPLAIN

    6.1 基本语法

    EXPLAIN 或 DESCRIBE语句的语法形式如下:

    EXPLAIN SELECT select_options
    或者
    DESCRIBE SELECT select_options
    
    • 1
    • 2
    • 3

    如果我们想看看某个查询的执行计划的话,可以在具体的查询语句前边加一个EXPLAIN ,就像这样:

    mysql> EXPLAIN SELECT 1;
    
    • 1

    EXPLAIN 语句输出的各个列的作用如下:

    在这里插入图片描述

    6.2 数据准备

    CREATE TABLE s1 (
    	id INT AUTO_INCREMENT,
    	key1 VARCHAR ( 100 ),
    	key2 INT,
    	key3 VARCHAR ( 100 ),
    	key_part1 VARCHAR ( 100 ),
    	key_part2 VARCHAR ( 100 ),
    	key_part3 VARCHAR ( 100 ),
    	common_field VARCHAR ( 100 ),
    	PRIMARY KEY ( id ),
    	INDEX idx_key1 ( key1 ),
    	UNIQUE INDEX idx_key2 ( key2 ),
    	INDEX idx_key3 ( key3 ),
    	INDEX idx_key_part ( key_part1, key_part2, key_part3 ) 
    ) ENGINE = INNODB CHARSET = utf8;
    CREATE TABLE s2 (
    	id INT AUTO_INCREMENT,
    	key1 VARCHAR ( 100 ),
    	key2 INT,
    	key3 VARCHAR ( 100 ),
    	key_part1 VARCHAR ( 100 ),
    	key_part2 VARCHAR ( 100 ),
    	key_part3 VARCHAR ( 100 ),
    	common_field VARCHAR ( 100 ),
    	PRIMARY KEY ( id ),
    	INDEX idx_key1 ( key1 ),
    	UNIQUE INDEX idx_key2 ( key2 ),
    	INDEX idx_key3 ( key3 ),
    INDEX idx_key_part ( key_part1, key_part2, key_part3 ) 
    ) ENGINE = INNODB CHARSET = utf8;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    设置参数 log_bin_trust_function_creators

    创建函数,假如报错,需开启如下命令:允许创建函数设置:

    set global log_bin_trust_function_creators=1; # 不加global只是当前窗口有效。
    
    • 1

    创建函数

    DELIMITER //
    CREATE FUNCTION rand_string1 ( n INT ) RETURNS VARCHAR ( 255 ) #该函数会返回一个字符串
    BEGIN
    	DECLARE
    		chars_str VARCHAR ( 100 ) DEFAULT 'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ';
    	DECLARE
    		return_str VARCHAR ( 255 ) DEFAULT '';
    	DECLARE
    		i INT DEFAULT 0;
    	WHILE
    			i < n DO
    			
    			SET return_str = CONCAT(
    				return_str,
    			SUBSTRING( chars_str, FLOOR( 1+RAND ()* 52 ), 1 ));
    		
    		SET i = i + 1;
    		
    	END WHILE;
    	RETURN return_str;
    	
    END // 
    DELIMITER;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    创建存储过程

    创建往s1表中插入数据的存储过程:

    DELIMITER //
    CREATE PROCEDURE insert_s1 (
    	IN min_num INT ( 10 ),
    	IN max_num INT ( 10 )) BEGIN
    	DECLARE
    		i INT DEFAULT 0;
    	
    	SET autocommit = 0;
    	REPEAT
    			
    			SET i = i + 1;
    		INSERT INTO s1
    		VALUES
    			(
    				( min_num + i ),
    				rand_string1 ( 6 ),
    				( min_num + 30 * i + 5 ),
    				rand_string1 ( 6 ),
    				rand_string1 ( 10 ),
    				rand_string1 ( 5 ),
    				rand_string1 ( 10 ),
    			rand_string1 ( 10 ));
    		UNTIL i = max_num 
    	END REPEAT;
    	COMMIT;
    	
    END // 
    DELIMITER;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    创建往s2表中插入数据的存储过程:

    DELIMITER //
    CREATE PROCEDURE insert_s2 (
    	IN min_num INT ( 10 ),
    	IN max_num INT ( 10 )) BEGIN
    	DECLARE
    		i INT DEFAULT 0;
    	
    	SET autocommit = 0;
    	REPEAT
    			
    			SET i = i + 1;
    		INSERT INTO s2
    		VALUES
    			(
    				( min_num + i ),
    				rand_string1 ( 6 ),
    				( min_num + 30 * i + 5 ),
    				rand_string1 ( 6 ),
    				rand_string1 ( 10 ),
    				rand_string1 ( 5 ),
    				rand_string1 ( 10 ),
    			rand_string1 ( 10 ));
    		UNTIL i = max_num 
    	END REPEAT;
    	COMMIT;
    	
    END // 
    DELIMITER;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    调用存储过程

    s1表数据的添加:加入1万条记录:

    CALL insert_s1(10001,10000);
    
    • 1

    s2表数据的添加:加入1万条记录:

    CALL insert_s2(10001,10000);
    
    • 1

    6.4 EXPLAIN各列作用

    1. table

    不论我们的查询语句有多复杂,里边儿包含了多少个表,到最后也是需要对每个表进行单表访问的,所以MySQL规定EXPLAIN语句输出的每条记录都对应着某个单表的访问方法,该条记录的table列代表着该表的表名(有时不是真实的表名字,可能是简称)。

    2. id

    我们写的查询语句一般都以SELECT 关键字开头,比较简单的查询语句里只有一个SELECT 关键字,比如下边这个查询语句:

    mysql> EXPLAIN SELECT * FROM s1 WHERE key1 = 'a';
    +----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+-------+
    | id | select_type | table | partitions | type | possible_keys | key      | key_len | ref   | rows | filtered | Extra |
    +----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+-------+
    |  1 | SIMPLE      | s1    | NULL       | ref  | idx_key1      | idx_key1 | 303     | const |    1 |   100.00 | NULL  |
    +----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+-------+
    1 row in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    mysql> EXPLAIN SELECT * FROM s1 INNER JOIN s2;
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+---------------------------------------+
    | id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra                                 |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+---------------------------------------+
    |  1 | SIMPLE      | s1    | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 9895 |   100.00 | NULL                                  |
    |  1 | SIMPLE      | s2    | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 9895 |   100.00 | Using join buffer (Block Nested Loop) |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+---------------------------------------+
    2 rows in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    mysql> EXPLAIN SELECT * FROM s1 WHERE key1 IN (SELECT key1 FROM s2) OR key3 = 'a';
    +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-------------+
    | id | select_type | table | partitions | type  | possible_keys | key      | key_len | ref  | rows | filtered | Extra       |
    +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-------------+
    |  1 | PRIMARY     | s1    | NULL       | ALL   | idx_key3      | NULL     | NULL    | NULL | 9895 |   100.00 | Using where |
    |  2 | SUBQUERY    | s2    | NULL       | index | idx_key1      | idx_key1 | 303     | NULL | 9895 |   100.00 | Using index |
    +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-------------+
    2 rows in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    mysql> EXPLAIN SELECT * FROM s1 WHERE key1 IN (SELECT key2 FROM s2 WHERE common_field
        -> = 'a');
    +----+-------------+-------+------------+------+---------------+----------+---------+--------------------+------+----------+------------------------------------+
    | id | select_type | table | partitions | type | possible_keys | key      | key_len | ref                | rows | filtered | Extra                              |
    +----+-------------+-------+------------+------+---------------+----------+---------+--------------------+------+----------+------------------------------------+
    |  1 | SIMPLE      | s1    | NULL       | ALL  | idx_key1      | NULL     | NULL    | NULL               | 9895 |   100.00 | Using where                        |
    |  1 | SIMPLE      | s2    | NULL       | ref  | idx_key2      | idx_key2 | 5       | atguigudb1.s1.key1 |    1 |    10.00 | Using index condition; Using where |
    +----+-------------+-------+------------+------+---------------+----------+---------+--------------------+------+----------+------------------------------------+
    2 rows in set, 2 warnings (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    mysql> EXPLAIN SELECT * FROM s1 UNION SELECT * FROM s2;
    +----+--------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
    | id | select_type  | table      | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra           |
    +----+--------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
    |  1 | PRIMARY      | s1         | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 9895 |   100.00 | NULL            |
    |  2 | UNION        | s2         | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 9895 |   100.00 | NULL            |
    | NULL | UNION RESULT | <union1,2> | NULL       | ALL  | NULL          | NULL | NULL    | NULL | NULL |     NULL | Using temporary |
    +----+--------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
    3 rows in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    mysql> EXPLAIN SELECT * FROM s1 UNION ALL SELECT * FROM s2;
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
    | id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
    |  1 | PRIMARY     | s1    | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 9895 |   100.00 | NULL  |
    |  2 | UNION       | s2    | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 9895 |   100.00 | NULL  |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
    2 rows in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • id如果相同,可以认为是一组,从上往下顺序执行
    • 在所有组中,id值越大,优先级越高,越先执行
    • 关注点:id号每个号码,表示一趟独立的查询, 一个sql的查询趟数越少越好
    3. select_type

    在这里插入图片描述

    mysql> EXPLAIN SELECT * FROM s1 INNER JOIN s2;
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+---------------------------------------+
    | id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra                                 |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+---------------------------------------+
    |  1 | SIMPLE      | s1    | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 9895 |   100.00 | NULL                                  |
    |  1 | SIMPLE      | s2    | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 9895 |   100.00 | Using join buffer (Block Nested Loop) |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+---------------------------------------+
    2 rows in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    mysql> EXPLAIN SELECT * FROM s1 UNION SELECT * FROM s2;
    +----+--------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
    | id | select_type  | table      | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra           |
    +----+--------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
    |  1 | PRIMARY      | s1         | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 9895 |   100.00 | NULL            |
    |  2 | UNION        | s2         | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 9895 |   100.00 | NULL            |
    | NULL | UNION RESULT | <union1,2> | NULL       | ALL  | NULL          | NULL | NULL    | NULL | NULL |     NULL | Using temporary |
    +----+--------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
    3 rows in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    mysql> EXPLAIN SELECT * FROM s1 WHERE key1 IN (SELECT key1 FROM s2) OR key3 = 'a';
    +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-------------+
    | id | select_type | table | partitions | type  | possible_keys | key      | key_len | ref  | rows | filtered | Extra       |
    +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-------------+
    |  1 | PRIMARY     | s1    | NULL       | ALL   | idx_key3      | NULL     | NULL    | NULL | 9895 |   100.00 | Using where |
    |  2 | SUBQUERY    | s2    | NULL       | index | idx_key1      | idx_key1 | 303     | NULL | 9895 |   100.00 | Using index |
    +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-------------+
    2 rows in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    mysql> EXPLAIN SELECT * FROM s1 WHERE key1 IN (SELECT key1 FROM s2 WHERE s1.key2 =
        -> s2.key2) OR key3 = 'a';
    +----+--------------------+-------+------------+------+-------------------+----------+---------+--------------------+------+----------+-------------+
    | id | select_type        | table | partitions | type | possible_keys     | key      | key_len | ref                | rows | filtered | Extra       |
    +----+--------------------+-------+------------+------+-------------------+----------+---------+--------------------+------+----------+-------------+
    |  1 | PRIMARY            | s1    | NULL       | ALL  | idx_key3          | NULL     | NULL    | NULL               | 9895 |   100.00 | Using where |
    |  2 | DEPENDENT SUBQUERY | s2    | NULL       | ref  | idx_key2,idx_key1 | idx_key2 | 5       | atguigudb1.s1.key2 |    1 |    10.00 | Using where |
    +----+--------------------+-------+------------+------+-------------------+----------+---------+--------------------+------+----------+-------------+
    2 rows in set, 2 warnings (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    mysql> EXPLAIN SELECT * FROM s1 WHERE key1 IN (SELECT key1 FROM s2 WHERE key1 =
        -> 'a' UNION SELECT key1 FROM s1 WHERE key1 = 'b');
    +----+--------------------+------------+------------+------+---------------+----------+---------+-------+------+----------+--------------------------+
    | id | select_type        | table      | partitions | type | possible_keys | key      | key_len | ref   | rows | filtered | Extra                    |
    +----+--------------------+------------+------------+------+---------------+----------+---------+-------+------+----------+--------------------------+
    |  1 | PRIMARY            | s1         | NULL       | ALL  | NULL          | NULL     | NULL    | NULL  | 9895 |   100.00 | Using where              |
    |  2 | DEPENDENT SUBQUERY | s2         | NULL       | ref  | idx_key1      | idx_key1 | 303     | const |    1 |   100.00 | Using where; Using index |
    |  3 | DEPENDENT UNION    | s1         | NULL       | ref  | idx_key1      | idx_key1 | 303     | const |    1 |   100.00 | Using where; Using index |
    | NULL | UNION RESULT       | <union2,3> | NULL       | ALL  | NULL          | NULL     | NULL    | NULL  | NULL |     NULL | Using temporary          |
    +----+--------------------+------------+------------+------+---------------+----------+---------+-------+------+----------+--------------------------+
    4 rows in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    mysql> EXPLAIN SELECT * FROM (SELECT key1, count(*) as c FROM s1 GROUP BY key1) AS
        -> derived_s1 where c > 1;
    +----+-------------+------------+------------+-------+---------------+----------+---------+------+------+----------+-------------+
    | id | select_type | table      | partitions | type  | possible_keys | key      | key_len | ref  | rows | filtered | Extra       |
    +----+-------------+------------+------------+-------+---------------+----------+---------+------+------+----------+-------------+
    |  1 | PRIMARY     | <derived2> | NULL       | ALL   | NULL          | NULL     | NULL    | NULL | 9895 |    33.33 | Using where |
    |  2 | DERIVED     | s1         | NULL       | index | idx_key1      | idx_key1 | 303     | NULL | 9895 |   100.00 | Using index |
    +----+-------------+------------+------------+-------+---------------+----------+---------+------+------+----------+-------------+
    2 rows in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    mysql> EXPLAIN SELECT * FROM s1 WHERE key1 IN (SELECT key1 FROM s2);
    +----+--------------+-------------+------------+--------+---------------+------------+---------+--------------------+------+----------+-------------+
    | id | select_type  | table       | partitions | type   | possible_keys | key        | key_len | ref                | rows | filtered | Extra       |
    +----+--------------+-------------+------------+--------+---------------+------------+---------+--------------------+------+----------+-------------+
    |  1 | SIMPLE       | s1          | NULL       | ALL    | idx_key1      | NULL       | NULL    | NULL               | 9895 |   100.00 | Using where |
    |  1 | SIMPLE       | <subquery2> | NULL       | eq_ref | <auto_key>    | <auto_key> | 303     | atguigudb1.s1.key1 |    1 |   100.00 | NULL        |
    |  2 | MATERIALIZED | s2          | NULL       | index  | idx_key1      | idx_key1   | 303     | NULL               | 9895 |   100.00 | Using index |
    +----+--------------+-------------+------------+--------+---------------+------------+---------+--------------------+------+----------+-------------+
    3 rows in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    4.type ☆

    完整的访问方法如下: system , const , eq_ref , ref , fulltext , ref_or_null ,index_merge , unique_subquery , index_subquery , range , index , ALL 。

    system

    mysql> CREATE TABLE t(i int) Engine=MyISAM;
    Query OK, 0 rows affected (0.05 sec)
    
    mysql> INSERT INTO t VALUES(1);
    Query OK, 1 row affected (0.01 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    然后我们看一下查询这个表的执行计划:

    mysql> EXPLAIN SELECT * FROM t;
    +----+-------------+-------+------------+--------+---------------+------+---------+------+------+----------+-------+
    | id | select_type | table | partitions | type   | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
    +----+-------------+-------+------------+--------+---------------+------+---------+------+------+----------+-------+
    |  1 | SIMPLE      | t     | NULL       | system | NULL          | NULL | NULL    | NULL |    1 |   100.00 | NULL  |
    +----+-------------+-------+------------+--------+---------------+------+---------+------+------+----------+-------+
    1 row in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    const

    mysql> EXPLAIN SELECT * FROM s1 WHERE id = 10005;
    +----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
    | id | select_type | table | partitions | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra |
    +----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
    |  1 | SIMPLE      | s1    | NULL       | const | PRIMARY       | PRIMARY | 4       | const |    1 |   100.00 | NULL  |
    +----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
    1 row in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    eq_ref

    mysql> EXPLAIN SELECT * FROM s1 INNER JOIN s2 ON s1.id = s2.id;
    +----+-------------+-------+------------+--------+---------------+---------+---------+------------------+------+----------+-------+
    | id | select_type | table | partitions | type   | possible_keys | key     | key_len | ref              | rows | filtered | Extra |
    +----+-------------+-------+------------+--------+---------------+---------+---------+------------------+------+----------+-------+
    |  1 | SIMPLE      | s1    | NULL       | ALL    | PRIMARY       | NULL    | NULL    | NULL             | 9895 |   100.00 | NULL  |
    |  1 | SIMPLE      | s2    | NULL       | eq_ref | PRIMARY       | PRIMARY | 4       | atguigudb1.s1.id |    1 |   100.00 | NULL  |
    +----+-------------+-------+------------+--------+---------------+---------+---------+------------------+------+----------+-------+
    2 rows in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    从执行计划的结果中可以看出,MySQL打算将s2作为驱动表,s1作为被驱动表,重点关注s1的访问方法是eq_ref ,表明在访问s1表的时候可以通过主键的等值匹配来进行访问。

    ref

    mysql> EXPLAIN SELECT * FROM s1 WHERE key1 = 'a';
    +----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+-------+
    | id | select_type | table | partitions | type | possible_keys | key      | key_len | ref   | rows | filtered | Extra |
    +----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+-------+
    |  1 | SIMPLE      | s1    | NULL       | ref  | idx_key1      | idx_key1 | 303     | const |    1 |   100.00 | NULL  |
    +----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+-------+
    1 row in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    ref_or_null

    mysql> EXPLAIN SELECT * FROM s1 WHERE key1 = 'a' OR key1 IS NULL;
    +----+-------------+-------+------------+-------------+---------------+----------+---------+-------+------+----------+-----------------------+
    | id | select_type | table | partitions | type        | possible_keys | key      | key_len | ref   | rows | filtered | Extra                 |
    +----+-------------+-------+------------+-------------+---------------+----------+---------+-------+------+----------+-----------------------+
    |  1 | SIMPLE      | s1    | NULL       | ref_or_null | idx_key1      | idx_key1 | 303     | const |    2 |   100.00 | Using index condition |
    +----+-------------+-------+------------+-------------+---------------+----------+---------+-------+------+----------+-----------------------+
    1 row in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    index_merge

    mysql> EXPLAIN SELECT * FROM s1 WHERE key1 = 'a' OR key3 = 'a';
    +----+-------------+-------+------------+-------------+-------------------+-------------------+---------+------+------+----------+---------------------------------------------+
    | id | select_type | table | partitions | type        | possible_keys     | key               | key_len | ref  | rows | filtered | Extra                                       |
    +----+-------------+-------+------------+-------------+-------------------+-------------------+---------+------+------+----------+---------------------------------------------+
    |  1 | SIMPLE      | s1    | NULL       | index_merge | idx_key1,idx_key3 | idx_key1,idx_key3 | 303,303 | NULL |    2 |   100.00 | Using union(idx_key1,idx_key3); Using where |
    +----+-------------+-------+------------+-------------+-------------------+-------------------+---------+------+------+----------+---------------------------------------------+
    1 row in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    从执行计划的type 列的值是index_merge 就可以看出,MySQL 打算使用索引合并的方式来执行对s1 表的查询。

    unique_subquery

    mysql> EXPLAIN SELECT * FROM s1 WHERE key2 IN (SELECT id FROM s2 where s1.key1 =
        -> s2.key1) OR key3 = 'a';
    +----+--------------------+-------+------------+-----------------+------------------+---------+---------+------+------+----------+-------------+
    | id | select_type        | table | partitions | type            | possible_keys    | key     | key_len | ref  | rows | filtered | Extra       |
    +----+--------------------+-------+------------+-----------------+------------------+---------+---------+------+------+----------+-------------+
    |  1 | PRIMARY            | s1    | NULL       | ALL             | idx_key3         | NULL    | NULL    | NULL | 9895 |   100.00 | Using where |
    |  2 | DEPENDENT SUBQUERY | s2    | NULL       | unique_subquery | PRIMARY,idx_key1 | PRIMARY | 4       | func |    1 |    10.00 | Using where |
    +----+--------------------+-------+------------+-----------------+------------------+---------+---------+------+------+----------+-------------+
    2 rows in set, 2 warnings (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    index_subquery

    mysql> EXPLAIN SELECT * FROM s1 WHERE common_field IN (SELECT key3 FROM s2 where
        -> s1.key1 = s2.key1) OR key3 = 'a';
    +----+--------------------+-------+------------+------+-------------------+----------+---------+--------------------+------+----------+-------------+
    | id | select_type        | table | partitions | type | possible_keys     | key      | key_len | ref                | rows | filtered | Extra       |
    +----+--------------------+-------+------------+------+-------------------+----------+---------+--------------------+------+----------+-------------+
    |  1 | PRIMARY            | s1    | NULL       | ALL  | idx_key3          | NULL     | NULL    | NULL               | 9895 |   100.00 | Using where |
    |  2 | DEPENDENT SUBQUERY | s2    | NULL       | ref  | idx_key1,idx_key3 | idx_key1 | 303     | atguigudb1.s1.key1 |    1 |    10.00 | Using where |
    +----+--------------------+-------+------------+------+-------------------+----------+---------+--------------------+------+----------+-------------+
    2 rows in set, 2 warnings (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    range

    mysql> EXPLAIN SELECT * FROM s1 WHERE key1 IN ('a', 'b', 'c');
    +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-----------------------+
    | id | select_type | table | partitions | type  | possible_keys | key      | key_len | ref  | rows | filtered | Extra                 |
    +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-----------------------+
    |  1 | SIMPLE      | s1    | NULL       | range | idx_key1      | idx_key1 | 303     | NULL |    3 |   100.00 | Using index condition |
    +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-----------------------+
    1 row in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    range

    mysql> EXPLAIN SELECT * FROM s1 WHERE key1 > 'a' AND key1 < 'b';
    +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-----------------------+
    | id | select_type | table | partitions | type  | possible_keys | key      | key_len | ref  | rows | filtered | Extra                 |
    +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-----------------------+
    |  1 | SIMPLE      | s1    | NULL       | range | idx_key1      | idx_key1 | 303     | NULL |  369 |   100.00 | Using index condition |
    +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-----------------------+
    1 row in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    index

    mysql> EXPLAIN SELECT key_part2 FROM s1 WHERE key_part3 = 'a';
    +----+-------------+-------+------------+-------+---------------+--------------+---------+------+------+----------+--------------------------+
    | id | select_type | table | partitions | type  | possible_keys | key          | key_len | ref  | rows | filtered | Extra                    |
    +----+-------------+-------+------------+-------+---------------+--------------+---------+------+------+----------+--------------------------+
    |  1 | SIMPLE      | s1    | NULL       | index | NULL          | idx_key_part | 909     | NULL | 9895 |    10.00 | Using where; Using index |
    +----+-------------+-------+------------+-------+---------------+--------------+---------+------+------+----------+--------------------------+
    1 row in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    ALL

    mysql> EXPLAIN SELECT * FROM s1;
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
    | id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
    |  1 | SIMPLE      | s1    | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 9895 |   100.00 | NULL  |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
    1 row in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    结果值从最好到最坏依次是: system > const > eq_ref > ref > fulltext > ref_or_null > index_merge >unique_subquery > index_subquery > range > index > ALL 其中比较重要的几个提取出来(见上图中的蓝色)。SQL 性能优化的目标:至少要达到 range 级别,要求是 ref 级别,最好是 consts级别。(阿里巴巴开发手册要求)

    5.possible_keys和key
    mysql> EXPLAIN SELECT * FROM s1 WHERE key1 > 'z' AND key3 = 'a';
    +----+-------------+-------+------------+------+-------------------+----------+---------+-------+------+----------+-------------+
    | id | select_type | table | partitions | type | possible_keys     | key      | key_len | ref   | rows | filtered | Extra       |
    +----+-------------+-------+------------+------+-------------------+----------+---------+-------+------+----------+-------------+
    |  1 | SIMPLE      | s1    | NULL       | ref  | idx_key1,idx_key3 | idx_key3 | 303     | const |    1 |     5.00 | Using where |
    +----+-------------+-------+------------+------+-------------------+----------+---------+-------+------+----------+-------------+
    1 row in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    6.key_len ☆
    mysql> EXPLAIN SELECT * FROM s1 WHERE key2 = 10126;
    +----+-------------+-------+------------+-------+---------------+----------+---------+-------+------+----------+-------+
    | id | select_type | table | partitions | type  | possible_keys | key      | key_len | ref   | rows | filtered | Extra |
    +----+-------------+-------+------------+-------+---------------+----------+---------+-------+------+----------+-------+
    |  1 | SIMPLE      | s1    | NULL       | const | idx_key2      | idx_key2 | 5       | const |    1 |   100.00 | NULL  |
    +----+-------------+-------+------------+-------+---------------+----------+---------+-------+------+----------+-------+
    1 row in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    key_len的长度计算公式:

    varchar(10)变长字段且允许NULL = 10 * ( character set:
    utf8=3,gbk=2,latin1=1)+1(NULL)+2(变长字段)
    varchar(10)变长字段且不允许NULL = 10 * ( character set:utf8=3,gbk=2,latin1=1)+2(变长字段)
    char(10)固定字段且允许NULL = 10 * ( character set:utf8=3,gbk=2,latin1=1)+1(NULL)
    char(10)固定字段且不允许NULL = 10 * ( character set:utf8=3,gbk=2,latin1=1)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    7. ref
    mysql> EXPLAIN SELECT * FROM s1 INNER JOIN s2 ON s1.id = s2.id;
    +----+-------------+-------+------------+--------+---------------+---------+---------+------------------+------+----------+-------+
    | id | select_type | table | partitions | type   | possible_keys | key     | key_len | ref              | rows | filtered | Extra |
    +----+-------------+-------+------------+--------+---------------+---------+---------+------------------+------+----------+-------+
    |  1 | SIMPLE      | s1    | NULL       | ALL    | PRIMARY       | NULL    | NULL    | NULL             | 9895 |   100.00 | NULL  |
    |  1 | SIMPLE      | s2    | NULL       | eq_ref | PRIMARY       | PRIMARY | 4       | atguigudb1.s1.id |    1 |   100.00 | NULL  |
    +----+-------------+-------+------------+--------+---------------+---------+---------+------------------+------+----------+-------+
    2 rows in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    mysql> EXPLAIN SELECT * FROM s1 INNER JOIN s2 ON s2.key1 = UPPER(s1.key1);
    +----+-------------+-------+------------+------+---------------+----------+---------+------+------+----------+-----------------------+
    | id | select_type | table | partitions | type | possible_keys | key      | key_len | ref  | rows | filtered | Extra                 |
    +----+-------------+-------+------------+------+---------------+----------+---------+------+------+----------+-----------------------+
    |  1 | SIMPLE      | s1    | NULL       | ALL  | NULL          | NULL     | NULL    | NULL | 9895 |   100.00 | NULL                  |
    |  1 | SIMPLE      | s2    | NULL       | ref  | idx_key1      | idx_key1 | 303     | func |    1 |   100.00 | Using index condition |
    +----+-------------+-------+------------+------+---------------+----------+---------+------+------+----------+-----------------------+
    2 rows in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    8. rows ☆
    mysql> EXPLAIN SELECT * FROM s1 WHERE key1 > 'z';
    +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-----------------------+
    | id | select_type | table | partitions | type  | possible_keys | key      | key_len | ref  | rows | filtered | Extra                 |
    +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-----------------------+
    |  1 | SIMPLE      | s1    | NULL       | range | idx_key1      | idx_key1 | 303     | NULL |  364 |   100.00 | Using index condition |
    +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-----------------------+
    1 row in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    9. filtered
    mysql> EXPLAIN SELECT * FROM s1 WHERE key1 > 'z' AND common_field = 'a';
    +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+------------------------------------+
    | id | select_type | table | partitions | type  | possible_keys | key      | key_len | ref  | rows | filtered | Extra                              |
    +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+------------------------------------+
    |  1 | SIMPLE      | s1    | NULL       | range | idx_key1      | idx_key1 | 303     | NULL |  364 |    10.00 | Using index condition; Using where |
    +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+------------------------------------+
    1 row in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    10.Extra ☆
    mysql> EXPLAIN SELECT * FROM s1 WHERE 1 != 1;
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+
    | id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra            |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+
    |  1 | SIMPLE      | NULL  | NULL       | NULL | NULL          | NULL | NULL    | NULL | NULL |     NULL | Impossible WHERE |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+
    1 row in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    mysql> EXPLAIN SELECT * FROM s1 WHERE common_field = 'a';
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
    | id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
    |  1 | SIMPLE      | s1    | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 9895 |    10.00 | Using where |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
    1 row in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    mysql> EXPLAIN SELECT MIN(key1) FROM s1 WHERE key1 = 'abcdefg';
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------------------+
    | id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra                   |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------------------+
    |  1 | SIMPLE      | NULL  | NULL       | NULL | NULL          | NULL | NULL    | NULL | NULL |     NULL | No matching min/max row |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------------------+
    1 row in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    mysql> EXPLAIN SELECT key1 FROM s1 WHERE key1 = 'a';
    +----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+-------------+
    | id | select_type | table | partitions | type | possible_keys | key      | key_len | ref   | rows | filtered | Extra       |
    +----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+-------------+
    |  1 | SIMPLE      | s1    | NULL       | ref  | idx_key1      | idx_key1 | 303     | const |    1 |   100.00 | Using index |
    +----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+-------------+
    1 row in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    mysql> EXPLAIN SELECT * FROM s1 ORDER BY key1 LIMIT 10;
    +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-------+
    | id | select_type | table | partitions | type  | possible_keys | key      | key_len | ref  | rows | filtered | Extra |
    +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-------+
    |  1 | SIMPLE      | s1    | NULL       | index | NULL          | idx_key1 | 303     | NULL |   10 |   100.00 | NULL  |
    +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-------+
    1 row in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    mysql> EXPLAIN SELECT key1, COUNT(*) AS amount FROM s1 GROUP BY key1;
    +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-------------+
    | id | select_type | table | partitions | type  | possible_keys | key      | key_len | ref  | rows | filtered | Extra       |
    +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-------------+
    |  1 | SIMPLE      | s1    | NULL       | index | idx_key1      | idx_key1 | 303     | NULL | 9895 |   100.00 | Using index |
    +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-------------+
    1 row in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • EXPLAIN不考虑各种Cache
    • EXPLAIN不能显示MySQL在执行查询时所作的优化工作
    • EXPLAIN不会告诉你关于触发器、存储过程的信息或用户自定义函数对查询的影响情况
    • 部分统计信息是估算的,并非精确值

    7.EXPLAIN的进一步使用

    JSON格式:在EXPLAIN单词和真正的查询语句中间加上FORMAT=JSON 。

    EXPLAIN FORMAT=JSON SELECT ....
    
    • 1
    mysql> EXPLAIN FORMAT=JSON SELECT s1.key1, s2.key1 FROM s1 LEFT JOIN s2 ON s1.key1 = s2.key1 WHERE s2.common_field is not null;
    | {
      "query_block": {
        "select_id": 1,
        "cost_info": {
          "query_cost": "12762.60"
        },
        "nested_loop": [
          {
            "table": {
              "table_name": "s2",
              "access_type": "ALL",
              "possible_keys": [
                "idx_key1"
              ],
              "rows_examined_per_scan": 9895,
              "rows_produced_per_join": 8905,
              "filtered": "90.00",
              "cost_info": {
                "read_cost": "294.90",
                "eval_cost": "1781.10",
                "prefix_cost": "2076.00",
                "data_read_per_join": "15M"
              },
              "used_columns": [
                "key1",
                "common_field"
              ],
              "attached_condition": "((`atguigudb1`.`s2`.`common_field` is not null) and (`atguigudb1`.`s2`.`key1` is not null))"
            }
          },
          {
            "table": {
              "table_name": "s1",
              "access_type": "ref",
              "possible_keys": [
                "idx_key1"
              ],
              "key": "idx_key1",
              "used_key_parts": [
                "key1"
              ],
              "key_length": "303",
              "ref": [
                "atguigudb1.s2.key1"
              ],
              "rows_examined_per_scan": 1,
              "rows_produced_per_join": 8905,
              "filtered": "100.00",
              "using_index": true,
              "cost_info": {
                "read_cost": "8905.50",
                "eval_cost": "1781.10",
                "prefix_cost": "12762.60",
                "data_read_per_join": "15M"
              },
              "used_columns": [
                "key1"
              ]
            }
          }
        ]
      }
    } |
    
    1 row in set, 1 warning (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
              "cost_info": {
                "read_cost": "294.90",
                "eval_cost": "1781.10",
                "prefix_cost": "2076.00",
                "data_read_per_join": "15M"
              },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    read_cost 是由下边这两部分组成的:

    • IO 成本
    • 检测rows × (1 - filter) 条记录的CPU 成本

    小贴士: rows和filter都是我们前边介绍执行计划的输出列,在JSON格式的执行计划中,rows相当于rows_examined_per_scan,filtered名称不变。

    • eval_cost 是这样计算的:

    检测 rows × filter 条记录的成本。

    • prefix_cost 就是单独查询s1 表的成本,也就是:read_cost + eval_cost

    • data_read_per_join 表示在此次查询中需要读取的数据量。

    对于s2 表的"cost_info" 部分是这样的:

              "cost_info": {
                "read_cost": "8905.50",
                "eval_cost": "1781.10",
                "prefix_cost": "12762.60",
                "data_read_per_join": "15M"
              },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    由于s2 表是被驱动表,所以可能被读取多次,这里的read_costeval_cost 是访问多次s2 表后累加起来的值,大家主要关注里边儿的prefix_cost 的值代表的是整个连接查询预计的成本,也就是单次查询s1 表和多次查询s2 表后的成本的和,也就是:

    8905.50+1781.1+2076=12762.6
    
    • 1

    8. MySQL监控分析视图-sys schema

    1. 主机相关:以host_summary开头,主要汇总了IO延迟的信息。
    2. Innodb相关:以innodb开头,汇总了innodb buffer信息和事务等待innodb锁的信息。
    3. I/o相关:以io开头,汇总了等待I/O、I/O使用量情况。
    4. 内存使用情况:以memory开头,从主机、线程、事件等角度展示内存的使用情况
    5. 连接与会话信息:processlist和session相关视图,总结了会话相关信息。
    6. 表相关:以schema_table开头的视图,展示了表的统计信息。
    7. 索引信息:统计了索引的使用情况,包含冗余索引和未使用的索引情况。
    8. 语句相关:以statement开头,包含执行全表扫描、使用临时表、排序等的语句信息。
    9. 用户相关:以user开头的视图,统计了用户使用的文件I/O、执行语句统计信息。
    10. 等待事件相关信息:以wait开头,展示等待事件的延迟情况。

    8.1Sys schema视图使用场景

    索引情况

    #1. 查询冗余索引
    select * from sys.schema_redundant_indexes;
    #2. 查询未使用过的索引
    select * from sys.schema_unused_indexes;
    #3. 查询索引的使用情况
    select index_name,rows_selected,rows_inserted,rows_updated,rows_deleted
    from sys.schema_index_statistics where table_schema='dbname' ;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    表相关

    # 1. 查询表的访问量
    select table_schema,table_name,sum(io_read_requests+io_write_requests) as io from
    sys.schema_table_statistics group by table_schema,table_name order by io desc;
    # 2. 查询占用bufferpool较多的表
    select object_schema,object_name,allocated,data
    from sys.innodb_buffer_stats_by_table order by allocated limit 10;
    # 3. 查看表的全表扫描情况
    select * from sys.statements_with_full_table_scans where db='dbname';
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    语句相关

    #1. 监控SQL执行的频率
    select db,exec_count,query from sys.statement_analysis
    order by exec_count desc;
    #2. 监控使用了排序的SQL
    select db,exec_count,first_seen,last_seen,query
    from sys.statements_with_sorting limit 1;
    #3. 监控使用了临时表或者磁盘临时表的SQL
    select db,exec_count,tmp_tables,tmp_disk_tables,query
    from sys.statement_analysis where tmp_tables>0 or tmp_disk_tables >0
    order by (tmp_tables+tmp_disk_tables) desc;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    IO相关

    #1. 查看消耗磁盘IO的文件
    select file,avg_read,avg_write,avg_read+avg_write as avg_io
    from sys.io_global_by_file_by_bytes order by avg_read limit 10;
    
    • 1
    • 2
    • 3

    Innodb 相关

    #1. 行锁阻塞情况
    select * from sys.innodb_lock_waits;
    
    • 1
    • 2
  • 相关阅读:
    Vue--插槽slot
    【linux】linux开发工具的使用
    【云原生之k8s】Helm 工具安装
    【无标题】
    三级网络技术总结
    Mac中隐私安全性设置-打开任何来源
    初探Hessian利用链为Dubbo-CVE占坑
    flink中interval join的flinkSQL实现以及状态的TTL过期时间
    关于#javascript#的问题:页面提交数据时,如何将提交的数据与bootstrapTable中的数据做比较,判断是否有重复提交的数据,如果有数据重复则弹窗提醒
    行业观察|车企数字化营销破局之道
  • 原文地址:https://blog.csdn.net/qq_51495235/article/details/133013890