@JunQiu
2018-09-27T16:06:37.000000Z
字数 9302
阅读 1725
mysql
explain select 语句
CREATE TABLE `user_info` (`id` BIGINT(20) NOT NULL AUTO_INCREMENT,`name` VARCHAR(50) NOT NULL DEFAULT '',`age` INT(11) DEFAULT NULL,PRIMARY KEY (`id`),KEY `name_index` (`name`));INSERT INTO user_info (name, age) VALUES ('xys', 20);INSERT INTO user_info (name, age) VALUES ('a', 21);INSERT INTO user_info (name, age) VALUES ('b', 23);INSERT INTO user_info (name, age) VALUES ('c', 50);INSERT INTO user_info (name, age) VALUES ('d', 15);INSERT INTO user_info (name, age) VALUES ('e', 20);INSERT INTO user_info (name, age) VALUES ('f', 21);INSERT INTO user_info (name, age) VALUES ('g', 23);INSERT INTO user_info (name, age) VALUES ('h', 50);INSERT INTO user_info (name, age) VALUES ('i', 15);CREATE TABLE `order_info` (`id` BIGINT(20) NOT NULL AUTO_INCREMENT,`user_id` BIGINT(20) DEFAULT NULL,`product_name` VARCHAR(50) NOT NULL DEFAULT '',`productor` VARCHAR(30) DEFAULT NULL,PRIMARY KEY (`id`),KEY `user_product_detail_index` (`user_id`, `product_name`, `productor`));INSERT INTO order_info (user_id, product_name, productor) VALUES (1, 'p1', 'WHH');INSERT INTO order_info (user_id, product_name, productor) VALUES (1, 'p2', 'WL');INSERT INTO order_info (user_id, product_name, productor) VALUES (1, 'p1', 'DX');INSERT INTO order_info (user_id, product_name, productor) VALUES (2, 'p1', 'WHH');INSERT INTO order_info (user_id, product_name, productor) VALUES (2, 'p5', 'WL');INSERT INTO order_info (user_id, product_name, productor) VALUES (3, 'p3', 'MA');INSERT INTO order_info (user_id, product_name, productor) VALUES (4, 'p1', 'WHH');INSERT INTO order_info (user_id, product_name, productor) VALUES (6, 'p1', 'WHH');INSERT INTO order_info (user_id, product_name, productor) VALUES (9, 'p8', 'TE');CREATE TABLE `order_info1` (`id` BIGINT(20) NOT NULL ,`user_id` BIGINT(20) DEFAULT NULL,);
mysql> explain select * from order_info\G //\G制表,使格式更加美观*************************** 1. row ***************************id: 1select_type: SIMPLEtable: order_infotype: indexpossible_keys: NULLkey: user_product_detail_indexkey_len: 254ref: NULLrows: 9Extra: Using index1 row in set (0.00 sec)## 先大概这些字段的含义:1、id:查询的标志,每个查询会自动分配一个id,比如使用union合并两个查询结果时没有id,为NULL。2、select_type:当前查询的类型,比如Simple SELECT (not using UNION or subqueries)。3、table:当前查询所对应的表,比如union对应两个表。4、type:可能是数据中最重要的字段,展示查询/连接是如何进行的,走索引/或者全表查询等等。5、possible_keys:当前查询可能会选择的索引,即可以使用该索引找到我们需要的行。6、key:当前查询实际用到的索引。7、key_len:所选择索引使用的长度。8、ref:jion查询的时候会用到,查询结果同哪个值比较。9、rows:当前查询必须要检测的行数。10、extra:一些额外的信息。11、filtered:被过滤条件过滤掉的数据的百分比。(但是根据文档上的意思应该是:过滤掉的数据为1-filtered)12、partitions:匹配的分区。
mysql> explain (SELECT * FROM user_info WHERE id IN (1, 2, 3)) UNION (SELECT * FROM user_info WHERE id IN (3, 4, 5))\G*************************** 1. row ***************************id: 1select_type: PRIMARYtable: user_infotype: rangepossible_keys: PRIMARYkey: PRIMARYkey_len: 8ref: NULLrows: 3Extra: Using where*************************** 2. row ***************************id: 2select_type: UNIONtable: user_infotype: rangepossible_keys: PRIMARYkey: PRIMARYkey_len: 8ref: NULLrows: 3Extra: Using where*************************** 3. row ***************************id: NULLselect_type: UNION RESULTtable: <union1,2>type: ALLpossible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: NULLExtra: Using temporary3 rows in set (0.00 sec)
// 以上面的例子的为例:id=1的查询最先开始,所以是PRIMARYid=2的查询是ubion中的第二个slect:所以是UNIONunion操作没有id为null,但是select_type是UNION// 比如写一个SUBQUERY???
# system : 当表中只有一条数据时,且是系统表时;如果不只一条数据时,分析与普通表相同。mysql> explain select * from time_zone\G*************************** 1. row ***************************id: 1select_type: SIMPLEtable: time_zonetype: systempossible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: 1Extra: NULL1 row in set (0.00 sec)# const : 当使用 PRIMARY KEY or UNIQUE index 去查询数据,因为他们是唯一的只用读取一次。mysql> explain select * from order_info where id=10 \G*************************** 1. row ***************************id: 1select_type: SIMPLEtable: order_infotype: constpossible_keys: PRIMARYkey: PRIMARYkey_len: 8ref: constrows: 1Extra: NULL1 row in set (0.00 sec)# eq_ref : 在多表join查询中,表示对于前表的每一个结果,都只能匹配到当前表的一行结果.(且通过PRIMARY KEY or UNIQUE NOT NULL index去查找) 并且查询的比较操作通常是 =, 查询效率较高。// exapmle:user_info.id(PRIMARY KEY)mysql> EXPLAIN SELECT * FROM user_info, order_info WHERE user_info.id = order_info.id\G*************************** 1. row ***************************id: 1select_type: SIMPLEtable: user_infotype: ALLpossible_keys: PRIMARYkey: NULLkey_len: NULLref: NULLrows: 10Extra: NULL*************************** 2. row ***************************id: 1select_type: SIMPLEtable: order_infotype: eq_refpossible_keys: PRIMARYkey: PRIMARYkey_len: 8ref: test.user_info.idrows: 1Extra: NULL2 rows in set (0.00 sec)Tips1:如果操作是>,此时type为all,因为并不能走索引。Tips2:有点意外的是,好像没有mysql并没有像我们想象的那样去连接,有机会了解一下。# ref : ref is used if the join uses only a leftmost prefix of the key or if the key is not a PRIMARY KEY or UNIQUE index .in other words, if the join cannot select a single row based on the key value.// user_id is leftmost prefixmysql> EXPLAIN SELECT * FROM user_info, order_info WHERE user_info.id = order_info.user_id\G*************************** 1. row ***************************id: 1select_type: SIMPLEtable: user_infotype: ALLpossible_keys: PRIMARYkey: NULLkey_len: NULLref: NULLrows: 10Extra: NULL*************************** 2. row ***************************id: 1select_type: SIMPLEtable: order_infotype: refpossible_keys: user_product_detail_indexkey: user_product_detail_indexkey_len: 9ref: test.user_info.idrows: 1Extra: Using index2 rows in set (0.00 sec)## fulltext:连接时使用FULLTEXT index## ref_or_null:This join type is like ref, but with the addition that MySQL does an extra search for rows that contain NULL values. (相比ref,多了null搜索)// 和常数连接,但order_info.user_id是leftmost prefix = ref,同时搜索null = ref_or_nullmysql> EXPLAIN SELECT * FROM order_info WHERE order_info.user_id=2 OR order_info.user_id is null\G*************************** 1. row ***************************id: 1select_type: SIMPLEtable: order_infotype: ref_or_nullpossible_keys: user_product_detail_indexkey: user_product_detail_indexkey_len: 9ref: constrows: 3Extra: Using where; Using index1 row in set (0.00 sec)## index_merge:This join type indicates that the Index Merge optimization is used.index_merge 可以看mysql optimize index_merge这篇日志或者官方:https://dev.mysql.com/doc/refman/8.0/en/index-merge-optimization.html## unique_subquery:This type replaces eq_ref for some IN subqueries of the following form:// value IN (SELECT primary_key FROM single_table WHERE some_expr)## index_subquery:This join type is similar to unique_subquery. It replaces IN subqueries, but it works for nonunique indexes in subqueries of the following form:value IN (SELECT key_column FROM single_table WHERE some_expr)## range:Only rows that are in a given range are retrieved, using an index to select the rows.(使用索引进行范围查找)mysql> EXPLAIN SELECT * FROM order_info WHERE id between 10 and 20\G*************************** 1. row ***************************id: 1select_type: SIMPLEtable: order_infotype: rangepossible_keys: PRIMARYkey: PRIMARYkey_len: 8ref: NULLrows: 10Extra: Using where1 row in set (0.02 sec)## index:The index join type is the same as ALL, except that the index tree is scanned. 包含两种情况:1、如果索引数据满足要求,仅扫描索引即可,the Extra column says Using index.2、通过索引扫描全表。Uses index does not appear in the Extra column.mysql> EXPLAIN SELECT id FROM order_info\G*************************** 1. row ***************************id: 1select_type: SIMPLEtable: order_infotype: indexpossible_keys: NULLkey: user_product_detail_indexkey_len: 254ref: NULLrows: 10Extra: Using index1 row in set (0.00 sec)## all:全表扫描
## 查看mysql优化后的SQL:mysql> EXPLAIN extended SELECT * FROM user_info, order_info1 WHERE user_info.id = order_info1.id\G*************************** 1. row ***************************id: 1select_type: SIMPLEtable: order_info1type: ALLpossible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: 1filtered: 100.00Extra: NULL*************************** 2. row ***************************id: 1select_type: SIMPLEtable: user_infotype: eq_refpossible_keys: PRIMARYkey: PRIMARYkey_len: 8ref: test.order_info1.idrows: 1filtered: 100.00Extra: NULL2 rows in set, 1 warning (0.00 sec)mysql> show warnings\G*************************** 1. row ***************************Level: NoteCode: 1003Message: /* select#1 */ select `test`.`user_info`.`id` AS `id`,`test`.`user_info`.`name` AS `name`,`test`.`user_info`.`age` AS `age`,`test`.`order_info1`.`id` AS `id`,`test`.`order_info1`.`user_id` AS `user_id` from `test`.`user_info` join `test`.`order_info1` where (`test`.`user_info`.`id` = `test`.`order_info1`.`id`)1 row in set (0.01 sec)## 一个奇怪的现象:其实就是extra的信息mysql> EXPLAIN SELECT * FROM order_info WHERE id =30\G*************************** 1. row ***************************id: 1select_type: SIMPLEtable: NULLtype: NULLpossible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: NULLExtra: Impossible WHERE noticed after reading const tables1 row in set (0.00 sec)实际上是:MySQL has read all const (and system) tables and notice that the WHERE clause is always false.