您的位置:首页 > 数据库 > MySQL

MySQL技巧#MySQL性能分析之explain的详解

2017-03-07 17:48 609 查看
EXPLAIN可以帮助开发人员分析SQL问题,explain显示了mysql如何使用索引来处理select语句以及连接表,可以帮助选择更好的索引和写出更优化的查询语句。

使用方法,在select语句前加上Explain就可以了:

Explain select * from jd_brands;


mysql在执行一条查询之前,会对发出的每条SQL进行分析,决定是否使用索引或全表扫描如果发送一条select * from blog where false,Mysql是不会执行查询操作的,因为经过SQL分析器的分析后MySQL已经清楚不会有任何语句符合操作。

mysql> explain select * from jd_brands where  name like '%(%';
+----+-------------+-----------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table     | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-----------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | jd_brands | ALL  | NULL          | NULL | NULL    | NULL | 9545 | Using where |
+----+-------------+-----------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)


1、id

2、select_type字段解释

1、SIMPLE

简单的SELECT,查询中不包含子查询或者UNION。

2、PRIMARY

查询中若包含任何复杂的子部分,最外层查询则被标记为:PRIMARY

3、UNION

UNION中的第二个或后面的select语句。

4、DEPENDENT UNION

union中的第二个或后面的select语句,取决于外面的查询。

5、UNION RESULT

union的结果。

6、SUBQUERY

子查询中的第一个select。

7、DEPENDENT SUBQUERY

子查询中的第一个select,取决于外面的查询。

8、DERIVED

导出表的select(from子句的子查询)。

3、table

显示这一行的数据是关于哪张表的。

4、type

这是重要的列,显示连接使用了何种类型。

system

表仅有一行,这是const类型的特列,平时不会出现,这个也可以忽略不计。

const

表最多有一个匹配行,const用于比较primary key 或者unique索引。因为只匹配一行数据,所以很快

记住一定是用到primary key 或者unique,并且只检索出两条数据的 情况下才会是const。

虽然只搜索一条数据,但是因为没有用到指定的索引,所以不会使用const,例如:

mysql> explain select * from jd_brands limit 1;
+----+-------------+-----------+------+---------------+------+---------+------+------+-------+
| id | select_type | table     | type | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+-----------+------+---------------+------+---------+------+------+-------+
|  1 | SIMPLE      | jd_brands | ALL  | NULL          | NULL | NULL    | NULL | 9545 | NULL  |
+----+-------------+-----------+------+---------------+------+---------+------+------+-------+
1 row in set (0.00 sec)


mysql> explain select * from jd_brands where id = 57;
+----+-------------+-----------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table     | type  | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+-----------+-------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | jd_brands | const | PRIMARY       | PRIMARY | 4       | const |    1 | NULL  |
+----+-------------+-----------+-------+---------------+---------+---------+-------+------+-------+
1 row in set (0.04 sec)


id是主键,所以使用了const。可以理解为const是最优化的。

eq_ref

对于eq_ref的解释,mysql手册是这样说的:”对于每个来自于前面的表的行组合,从该表中读取一行。这可能是最好的联接类型,除了const类型。它用在一个索引的所有部分被联接使用并且索引是UNIQUE或PRIMARY KEY”。eq_ref可以用于使用=比较带索引的列。

mysql> explain select * from jd_brands as b left join jd_category as c on b.cate_id=c.id;
+----+-------------+-------+--------+---------------+---------+---------+---------------------+-------+-------------+
| id | select_type | table | type   | possible_keys | key     | key_len | ref                 | rows  | Extra       |
+----+-------------+-------+--------+---------------+---------+---------+---------------------+-------+-------------+
|  1 | SIMPLE      | b     | ALL    | NULL          | NULL    | NULL    | NULL                | 21285 | NULL        |
|  1 | SIMPLE      | c     | eq_ref | PRIMARY       | PRIMARY | 4       | hailebang.b.cate_id |     1 | Using where |
+----+-------------+-------+--------+---------------+---------+---------+---------------------+-------+-------------+
2 rows in set (0.04 sec)


ref

对于每个来自于前面的表的行组合,所有有匹配索引值的行将从这张表中读取。如果联接只使用键的最左边的前缀,或如果键不是UNIQUE或PRIMARY KEY(换句话说,如果联接不能基于关键字选择单个行的话),则使用ref。如果使用的键仅仅匹配少量行,该联接类型是不错的。

range

mysql> explain select * from jd_brands where id between 57 and 58;;
+----+-------------+-----------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table     | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+-------------+-----------+-------+---------------+---------+---------+------+------+-------------+
|  1 | SIMPLE      | jd_brands | range | PRIMARY       | PRIMARY | 4       | NULL |    1 | Using where |
+----+-------------+-----------+-------+---------------+---------+---------+------+------+-------------+
1 row in set (0.04 sec)

mysql> explain select * from jd_brands where id in (57 ,58);
+----+-------------+-----------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table     | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+-------------+-----------+-------+---------------+---------+---------+------+------+-------------+
|  1 | SIMPLE      | jd_brands | range | PRIMARY       | PRIMARY | 4       | NULL |    2 | Using where |
+----+-------------+-----------+-------+---------------+---------+---------+------+------+-------------+
1 row in set (0.03 sec)

mysql> explain select * from jd_brands where id > 67;
+----+-------------+-----------+-------+---------------+---------+---------+------+-------+-------------+
| id | select_type | table     | type  | possible_keys | key     | key_len | ref  | rows  | Extra       |
+----+-------------+-----------+-------+---------------+---------+---------+------+-------+-------------+
|  1 | SIMPLE      | jd_brands | range | PRIMARY       | PRIMARY | 4       | NULL | 10642 | Using where |
+----+-------------+-----------+-------+---------------+---------+---------+------+-------+-------------+
1 row in set (0.04 sec)


indexhe

ALL

possible_keys

显示可能应用在这张表中的索引。如果为空,没有可能的索引。可以为相关的域从WHERE语句中选择一个合适的语句

5、key

实际使用的索引。如果为NULL,则没有使用索引。很少的情况下,MYSQL会选择优化不足的索引。这种情况下,可以在SELECT语句中使用USE INDEX(indexname)来强制使用一个索引或者用IGNORE INDEX(indexname)来强制MYSQL忽略索引

6、key_len

使用的索引的长度。在不损失精确性的情况下,长度越短越好

7、ref

显示索引的哪一列被使用了,如果可能的话,是一个常数

8、rows

MYSQL认为必须检查的用来返回请求数据的行数

9、Extra

关于MYSQL如何解析查询的额外信息。坏的例子是Using temporary和Using filesort,意思MYSQL根本不能使用索引,结果是检索会很慢。

1、Distinct

一旦MYSQL找到了与行相联合匹配的行,就不再搜索了

2、Not exists

MYSQL优化了LEFT JOIN,一旦它找到了匹配LEFT JOIN标准的行,就不再搜索了

3、Range checked for each Record(index map:#)

没有找到理想的索引,因此对于从前面表中来的每一个行组合,MYSQL检查使用哪个索引,并用它来从表中返回行。这是使用索引的最慢的连接之一

4、Using filesort:

看到这个的时候,查询就需要优化了。MYSQL需要进行额外的步骤来发现如何对返回的行排序。它根据连接类型以及存储排序键值和匹配条件的全部行的行指针来排序全部行

5、Using index

列数据是从仅仅使用了索引中的信息而没有读取实际的行动的表返回的,这发生在对表的全部的请求列都是同一个索引的部分的时候

6、Using temporary

看到这个的时候,查询需要优化了。这里,MYSQL需要创建一个临时表来存储结果,这通常发生在对不同的列集进行ORDER BY上,而不是GROUP BY上

7、Where used

使用了WHERE从句来限制哪些行将与下一张表匹配或者是返回给用户。如果不想返回表中的全部行,并且连接类型ALL或index,这就会发生,或者是查询有问题不同连接类型的解释(按照效率高低的顺序排序)

8、system

表只有一行:system表。这是const连接类型的特殊情况

9、const

表中的一个记录的最大值能够匹配这个查询(索引可以是主键或惟一索引)。因为只有一行,这个值实际就是常数,因为MYSQL先读这个值然后把它当做常数来对待

10、eq_ref

在连接中,MYSQL在查询时,从前面的表中,对每一个记录的联合都从表中读取一个记录,它在查询使用了索引为主键或惟一键的全部时使用

11、ref

这个连接类型只有在查询使用了不是惟一或主键的键或者是这些类型的部分(比如,利用最左边前缀)时发生。对于之前的表的每一个行联合,全部记录都将从表中读出。这个类型严重依赖于根据索引匹配的记录多少—越少越好

12、range

这个连接类型使用索引返回一个范围中的行,比如使用>或<查找东西时发生的情况

13、index:

这个连接类型对前面的表中的每一个记录联合进行完全扫描(比ALL更好,因为索引一般小于表数据)

14、ALL

这个连接类型对于前面的每一个记录联合进行完全扫描,这一般比较糟糕,应该尽量避免.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  mysql explain