EXPLAIN语句能够用做DESCRIBE的一个同义词,或得到关于MySQL如何执行SELECT语句的信息:EXPLAIN tbl_name是DESCRIBE tbl_name或SHOW COLUMNS FROM tbl_name的一个同义词。html
· 若是在SELECT语句前放上关键词EXPLAIN,MySQL将解释它如何处理SELECT,提供有关表如何联接和联接的次序。mysql
借助于EXPLAIN,能够知道何时必须为表加入索引以获得一个使用索引来寻找记录的更快的SELECT。还能够知道优化器是否以一个最佳次序联接表。为了强制优化器让一个SELECT语句按照表命名顺序的联接次序,语句应以STRAIGHT_JOIN而不仅是SELECT开头。算法
查看执行计划,能够分析SQL合理地使用存在的索引,或调整当前的索引。sql
语法:服务器
explain <sql语句> 或者 explain [extended] <sql语句> 或 explain partitions <sql语句>函数
EXPLAIN为用于SELECT语句中的每一个表返回一行信息。表以它们在处理查询过程当中将被MySQL读入的顺序被列出。MySQL用一遍扫描屡次联接(single-sweep multi-join)的方式解决全部联接。这意味着MySQL从第一个表中读一行,而后找到在第二个表中的一个匹配行,而后在第3个表中等等。当全部的表处理完后,它输出选中的列而且返回表清单直到找到一个有更多的匹配行的表。从该表读入下一行并继续处理下一个表。性能
当使用EXTENDED关键字时,EXPLAIN产生附加信息,用于将执行计划‘反编译’成SQL语句,运行show warnings 可等到优化后的查询语句,包括优化器限定SELECT语句中的表和列名,重写而且执行优化规则后SELECT语句是什么样子,而且还可能包括优化过程的其它注解。 优化
Partitions用于分区表的执行计划。server
注:也可使用desc命令来查看执行计划,用法desc <sql语句>htm
mysql> explain select * from order_item;
+----+-------------+------------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+------+---------------+------+---------+------+------+-------+
| 1 | SIMPLE | order_item | ALL | NULL | NULL | NULL | NULL | 4553 | |
+----+-------------+------------+------+---------------+------+---------+------+------+-------+
1 row in set (0.00 sec)
mysql> desc select * from order_item;
+----+-------------+------------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+------+---------------+------+---------+------+------+-------+
| 1 | SIMPLE | order_item | ALL | NULL | NULL | NULL | NULL | 4553 | |
+----+-------------+------------+------+---------------+------+---------+------+------+-------+
1 row in set (0.02 sec)
EXPLAIN的每一个输出行提供一个表的相关信息,而且每一个行包括下面的列:
• id SELECT识别符。这是SELECT的查询序列号。
例:
mysql> explain select * from (select * from (select * from tb where id = 4) a) b;
+----+-------------+------------+--------+---------------+---------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+---------------+---------+---------+------+------+-------+
| 1 | PRIMARY | <derived2> | system | NULL | NULL | NULL | NULL | 1 | |
| 2 | DERIVED | <derived3> | system | NULL | NULL | NULL | NULL | 1 | |
| 3 | DERIVED | tb | const | PRIMARY | PRIMARY | 4 | | 1 | |
+----+-------------+------------+--------+---------------+---------+---------+------+------+-------+
3 rows in set (0.59 sec)
这条SQL的执行顺序是从里向外的执行,就是从id=3 向上执行。说明:对于子查询,id的序号会递增,id值越大优先级越高,越先被执行
mysql> explain select s.id, s.sname from student s, sc, course c where s.id=sc.sid and sc.cid = c.id and c.tid = '1001';
+----+-------------+-------+--------+---------------+---------+---------+---------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+---------+---------+---------------+------+-------------+
| 1 | SIMPLE | s | ALL | PRIMARY | NULL | NULL | NULL | 1 | |
| 1 | SIMPLE | sc | ref | sid,cid | sid | 5 | testdb.s.id | 1 | Using where |
| 1 | SIMPLE | c | eq_ref | PRIMARY,tid | PRIMARY | 4 | testdb.sc.cid | 1 | Using where |
+----+-------------+-------+--------+---------------+---------+---------+---------------+------+-------------+
3 rows in set (0.00 sec)
这条SQL的执行顺序是从左到右,说明:id相同时,执行顺序由上至下
id若是相同,能够认为是一组,从上往下顺序执行;在全部组中,id值越大,优先级越高,越先执行
• select_type SELECT类型,能够为如下任何一种:
o SIMPLE 简单SELECT(不含UNION或子查询)
o PRIMARY 子查询中的最外层查询,(不是主键查询)
o UNION UNION中的第二个或后面的SELECT语句(第一个SELECT 为PRIMARY)
o DEPENDENT UNION UNION中的第二个或后面的SELECT语句,取决于外面的查询
o UNION RESULT UNION的结果。
o SUBQUERY 子查询中的第一个SELECT,结果不依赖于外部查询结果集;
o DEPENDENT SUBQUERY 子查询中的第一个SELECT,取决于外面的查询
o DERIVED 导出表的SELECT(FROM子句的子查询)
• table 输出的行所引用的表。
• type 联接类型,表示MySQL在表中找到所需行的方式,又称“访问类型”。下面给出各类联接类型,按照从最佳类型到最坏类型进行排序:
常见类型以下:
由左至右,性能由最差到最好
o NULL MySQL在优化过程当中分解语句,执行时甚至不用访问表域索引。
o system 表仅有一行(=系统表)。这是const联接类型的一个特例。
o const 读常量,且最多只会有一条记录匹配。const表很快,由于它们只读取一次!
const可用于常数值比较PRIMARY KEY或UNIQUE索引的全部部分。例:在下面的查询中,tbl_name能够用于const表:
SELECT * from tbl_name WHERE primary_key=1;
SELECT * from tbl_name WHERE primary_key_part1=1和 primary_key_part2=2;
例:
mysql> explain select * from student where id=1001;
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
| 1 | SIMPLE | student | const | PRIMARY | PRIMARY | 4 | const | 1 | |
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
1 row in set (0.00 sec)
主键位于Where列表中,MySQL将该查询转换为一个常量。例:
或mysql> explain select * from (select * from student where id=1001) t;
+----+-------------+------------+--------+---------------+---------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+---------------+---------+---------+------+------+-------+
| 1 | PRIMARY | <derived2> | system | NULL | NULL | NULL | NULL | 1 | |
| 2 | DERIVED | student | const | PRIMARY | PRIMARY | 4 | | 1 | |
+----+-------------+------------+--------+---------------+---------+---------+------+------+-------+
2 rows in set (0.00 sec)
o eq_ref (惟一性索引扫描) 最多只会有一条匹配结果,通常是经过主键或者惟一键索引来访问; eq_ref能够用于使用= 操做符比较的带索引的列。比较值能够为常量或一个使用在该表前面所读取的表的列的表达式。
例:在下面的例子中,MySQL可使用eq_ref联接来处理ref_tables:
SELECT * FROM ref_table, other_table WHERE ref_table.key_column=other_table.column;
SELECT * FROM ref_table, other_table WHERE ref_table.key_column_part1=other_table.column AND ref_table.key_column_part2=1;
例:
mysql> explain select * from teacher t, teacher t1 where t.id = t1.id; --惟一性索引扫描,对于每一个索引键,表中只有一条记录与之匹配。常见于主键或惟一索引扫描
+----+-------------+-------+--------+---------------+---------+---------+-------------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+---------+---------+-------------+------+-------+
| 1 | SIMPLE | t | ALL | PRIMARY | NULL | NULL | NULL | 1 | |
| 1 | SIMPLE | t1 | eq_ref | PRIMARY | PRIMARY | 4 | testdb.t.id | 1 | |
+----+-------------+-------+--------+---------------+---------+---------+-------------+------+-------+
2 rows in set (0.00 sec)
o ref (非惟一性索引扫描) 返回匹配某个单独值的全部行,常见于使用非惟一索引或惟一索引的非惟一前缀进行的查找
Join 语句中被驱动表索引引用查询:对于每一个来自于前面的表的行组合,全部有匹配索引值的行将从这张表中读取。若是联接只使用键的最左边的前缀,或若是键不是UNIQUE或PRIMARY KEY(换句话说,若是联接不能基于关键字选择单个行的话),则使用ref。若是使用的键仅仅匹配少许行,该联接类型是不错的。ref能够用于使用=或<=>操做符的带索引的列。
例:在下面的例子中,MySQL可使用ref联接来处理ref_tables:
SELECT * FROM ref_table WHERE key_column=expr;
SELECT * FROM ref_table, other_table WHERE ref_table.key_column=other_table.column;
SELECT * FROM ref_table,other_table WHERE ref_table.key_column_part1=other_table.column AND ref_table.key_column_part2=1;
例:
mysql> select * from teacher t, course c where t.id=c.tid;
+------+-------+------+---------+------+
| id | tname | id | cname | tid |
+------+-------+------+---------+------+
| 2010 | wang | 1011 | english | 2010 |
+------+-------+------+---------+------+
1 row in set (0.00 sec)
mysql>
mysql> explain select * from teacher t, course c where t.id=c.tid; --非惟一性索引扫描,返回匹配某个单独值的全部行。常见于使用非惟一索引即惟一索引的非惟一前缀进行的查找
+----+-------------+-------+------+---------------+------+---------+-------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+-------------+------+-------------+
| 1 | SIMPLE | t | ALL | PRIMARY | NULL | NULL | NULL | 1 | |
| 1 | SIMPLE | c | ref | tid | tid | 5 | testdb.t.id | 1 | Using where |
+----+-------------+-------+------+---------------+------+---------+-------------+------+-------------+
2 rows in set (0.00 sec)
o ref_or_null 该联接类型如同ref,可是添加了MySQL能够专门搜索包含NULL值的行。在解决子查询中常用该联接类型的优化。与ref 惟一区别就是在使用索引引用查询以外再增长一个空值的查询;参见7.2.7节,“MySQL如何优化IS NULL”。
例:在下面的例子中,MySQL可使用ref_or_null联接来处理ref_tables:
SELECT * FROM ref_table WHERE key_column=expr OR key_column IS NULL;
o index_merge 查询中同时使用两个(或更多)索引,而后对索引结果进行merge 以后再读取表数据。在这种状况下,key列包含了使用的索引的清单,key_len包含了使用的索引的最长的关键元素。详细信息参见7.2.6节,“索引合并优化”。
o unique_subquery 子查询中的返回结果字段组合是主键或者惟一约束。该类型替换了下面形式的IN子查询的ref:
value IN (SELECT primary_key FROM single_table WHERE some_expr)
unique_subquery是一个索引查找函数,能够彻底替换子查询,效率更高。
o index_subquery 子查询中的返回结果字段组合是一个索引(或索引组合),但不是一个主键或者惟一索引。该联接类型相似于unique_subquery,能够替换IN子查询,但只适合下列形式的子查询中的非惟一索引:
value IN (SELECT key_column FROM single_table WHERE some_expr)
o range (索引范围扫描) :只检索给定范围的行,使用一个索引来选择行。key列显示使用了哪一个索引。key_len包含所使用索引的最长关键元素。在该类型中ref列为NULL。当使用=、<>、>、>=、<、<=、IS NULL、<=>、BETWEEN或者IN操做符,用常量比较关键字列时,可使用range:
例: SELECT * FROM tbl_name WHERE key_column = 10;
SELECT * FROM tbl_name WHERE key_column BETWEEN 10 and 20;
SELECT * FROM tbl_name WHERE key_column IN (10,20,30);
SELECT * FROM tbl_name WHERE key_part1= 10 AND key_part2 IN (10,20,30);
例:
mysql> explain select * from course where tid between 2000 and 3000; --索引范围扫描,对索引的扫描开始于某一点,返回匹配值域的行,常见于between、<、>等的查询
+----+-------------+--------+-------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+-------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | course | range | tid | tid | 5 | NULL | 1 | Using where |
+----+-------------+--------+-------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
注意,在对主键使用between 或in 等查询时,也多是:
mysql> explain select * from teacher where id between 2000 and 3000;
+----+-------------+---------+-------+---------------+-------+---------+------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref |rows | Extra |
+----+-------------+---------+-------+---------------+-------+---------+------+------+--------------------------+
| 1 | SIMPLE | teacher | index | PRIMARY | tname | 43 | NULL | 1 | Using where; Using index |
+----+-------------+---------+-------+---------------+-------+---------+------+------+--------------------------+
1 row in set (0.00 sec)
mysql> explain select * from teacher where id in (2000, 3000);
+----+-------------+---------+-------+---------------+-------+---------+------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref |rows | Extra |
+----+-------------+---------+-------+---------------+-------+---------+------+------+--------------------------+
| 1 | SIMPLE | teacher | index | PRIMARY | tname | 43 | NULL | 1 | Using where; Using index |
+----+-------------+---------+-------+---------------+-------+---------+------+------+--------------------------+
1 row in set (0.00 sec)
o index (全索引扫描) :该联接类型与ALL相同,除了只有索引树被扫描。这一般比ALL快,由于索引文件一般比数据文件小。当查询只使用做为单索引一部分的列时,MySQL可使用该联接类型。
o ALL (全表扫描):对于每一个来自于先前的表的行组合,进行完整的表扫描。若是表是第一个没标记const的表,这一般很差,而且一般在它状况下不好。一般能够增长更多的索引而不要使用ALL,使得行能基于前面的表中的常数值或列值被检索出。
• possible_keys 该查询能够利用的索引。 若是没有任何索引可使用,就会显示成null,在这种状况下,能够经过检查WHERE子句看是否它引用某些列或适合索引的列来提升你的查询性能。若是是这样,创造一个适当的索引而且再次用EXPLAIN检查查询。参见13.1.2节,“ALTER TABLE语法”。
为了看清一张表有什么索引,使用SHOW INDEX FROM tbl_name。
• key key列显示MySQL实际从possible_keys 中所选择使用的键(索引)。若是没有选择索引,键是NULL。要想强制MySQL使用或忽视possible_keys列中的索引,在查询中使用FORCE INDEX、USE INDEX或者IGNORE INDEX。参见13.2.7节,“SELECT语法”。
对于MyISAM和BDB表,运行ANALYZE TABLE能够帮助优化器选择更好的索引。对于MyISAM表,可使用myisamchk --analyze。参见13.5.2.1节,“ANALYZE TABLE语法”和5.9.4节,“表维护和崩溃恢复”。
• key_len 被选中使用索引的索引键长度。若是键是NULL,则长度为NULL。注意经过key_len值咱们能够肯定MySQL将实际使用一个多部关键字的几个部分。
例:
mysql> explain select cname from course; -- 没有利用到索引
+----+-------------+--------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+------+---------------+------+---------+------+------+-------+
| 1 | SIMPLE | course | ALL | NULL | NULL | NULL | NULL |1 | |
+----+-------------+--------+------+---------------+------+---------+------+------+-------+
1 row in set (0.00 sec)
mysql> explain select * from course where tid = 2002; -- 这里存在一个外键索引
+----+-------------+--------+------+---------------+------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+------+---------------+------+---------+-------+------+-------------+
| 1 | SIMPLE | course | ref | tid | tid | 5 | const | 1 | Using where |
+----+-------------+--------+------+---------------+------+---------+-------+------+-------------+
1 row in set (0.00 sec)
key_len显示的值为索引字段的最大可能长度,并不是实际使用长度,即key_len是根据表定义计算而得,不是经过表内检索出的
• ref 列出是经过常量(const),仍是某个表的某个字段(若是是join)来过滤(经过key)的;
例:
mysql> explain select * from teacher t, course c where t.id=c.tid and c.cname='ac';
+----+-------------+-------+-------+---------------+-------+---------+-------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+-------+---------+-------------+------+-------------+
| 1 | SIMPLE | t | index | PRIMARY | tname | 43 | NULL | 1 | Using index |
| 1 | SIMPLE | c | ref | tid | tid | 5 | testdb.t.id | 1 | Using where |
+----+-------------+-------+-------+---------------+-------+---------+-------------+------+-------------+
2 rows in set (0.00 sec)
本例中,由key_len可知course表的tid被充分使用,course表的tid匹配teacher表的id,course表的cname匹配’ac’。
• rows rows列显示MySQL认为它执行查询时必须检查的行数。
• Extra 该列包含MySQL解决查询的详细信息。下面解释了该列能够显示的不一样的文本字符串:
o Distinct MySQL找到了第一条匹配的结果后,将中止该值的查询而转为后面其余值的查询;
o Not exists MySQL可以对查询进行LEFT JOIN优化,发现1个匹配LEFT JOIN标准的行后,再也不为前面的的行组合在该表内检查更多的行。
下面是一个能够这样优化的查询类型的例子:
SELECT * 从t1 LEFT JOIN t2 ON t1.id=t2.id WHERE t2.id IS NULL;
假定t2.id定义为NOT NULL。在这种状况下,MySQL使用t1.id的值扫描t1并查找t2中的行。若是MySQL在t2中发现一个匹配的行,它知道t2.id毫不会为NULL,而且再也不扫描t2内有相同的id值的行。换句话说,对于t1的每一个行,MySQL只须要在t2中查找一次,不管t2内实际有多少匹配的行。
o range checked for each record (index map: #) MySQL没有发现好的可使用的索引,但发现若是来自前面的表的列值已知,可能部分索引可使用。对前面的表的每一个行组合,MySQL检查是否可使用range或index_merge访问方法来索取行。关于适用性标准的描述参见7.2.5节,“范围优化”和7.2.6节,“索引合并优化”,不一样的是前面表的全部列值已知而且认为是常量。这并不很快,但比执行没有索引的联接要快得多。
o Using filesort(使用文件排序) 当Query 中包含ORDER BY 操做,并且没法利用索引完成排序操做的时候,MySQL Query Optimizer 不得不选择相应的排序算法(文件排序)来实现。参见7.2.12节,“MySQL如何优化ORDER BY”。
o Using index(使用索引排序) 所须要的数据只须要在Index 便可所有得到而不须要再到表中取数据。当查询只使用做为单一索引一部分的列时,可使用该策略。
例:
mysql> explain select * from teacher where tname like 'tom';
+----+-------------+---------+-------+---------------+-------+---------+------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref |rows | Extra |
+----+-------------+---------+-------+---------------+-------+---------+------+------+--------------------------+
| 1 | SIMPLE | teacher | index | tname | tname | 43 | NULL | 1 | Using where; Using index |
+----+-------------+---------+-------+---------------+-------+---------+------+------+--------------------------+
1 row in set (0.00 sec)
若是是mysql> explain select id, tname from teacher where tname like 'tom';
+----+-------------+---------+-------+---------------+-------+---------+------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref |rows | Extra |
+----+-------------+---------+-------+---------------+-------+---------+------+------+--------------------------+
| 1 | SIMPLE | teacher | index | tname | tname | 43 | NULL | 1 | Using where; Using index |
+----+-------------+---------+-------+---------------+-------+---------+------+------+--------------------------+
1 row in set (0.00 sec)
覆盖索引(Covering Index):MySQL能够利用索引返回select列表中的字段,而没必要根据索引再次读取数据文件,包含全部知足查询须要的数据的索引称为 覆盖索引(Covering Index)
注意: 若是要使用覆盖索引,必定要注意select列表中只取出须要的列,不可select *,由于若是将全部字段一块儿作索引会致使索引文件过大,查询性能降低。
o Using temporary(使用临时表) 当MySQL 在某些操做中必须使用临时表的时候(使用临时表来存储结果集),在Extra 信息中就会出现Using temporary 。主要常见于GROUP BY 和ORDER BY (分组与排序)等操做中。
mysql> explain select * from course where id in (1000, 3000) group by cname;
+----+-------------+--------+-------+---------------+---------+---------+------+------+----------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+-------+---------------+---------+---------+------+------+----------------------------------+
| 1 | SIMPLE | course | range | PRIMARY | PRIMARY | 4 | NULL | 2 | Using where; Using temporary; Using filesort |
+----+-------------+--------+-------+---------------+---------+---------+------+------+---------------------------------+
1 row in set (0.00 sec)
注意的是,若是cname上存在索引,则结果就不同了,如,在teacher表的tname存在惟一约束,故:
mysql> explain select * from teacher where id in (2000, 3000) group by tname;
+----+-------------+---------+-------+---------------+-------+---------+------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref |rows | Extra |
+----+-------------+---------+-------+---------------+-------+---------+------+------+--------------------------+
| 1 | SIMPLE | teacher | index | PRIMARY | tname | 43 | NULL | 1 | Using where; Using index |
+----+-------------+---------+-------+---------------+-------+---------+------+------+--------------------------+
1 row in set (0.00 sec)
o Using where (使用子句过滤) 若是不是读取表的全部数据,或者不是仅仅经过索引就能够获取全部须要的数据,则会出现Using where 信息。若是想要使查询尽量快,应找出Using filesort 和Using temporary的Extra值。
若是查询未能使用索引,Using where的做用只是提醒咱们MySQL将用where子句来过滤结果集
mysql> explain select * from course where cname like 'english';
+----+-------------+--------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | course | ALL | NULL | NULL | NULL | NULL |1 | Using where |
+----+-------------+--------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
o Using sort_union(...), Using union(...), Using intersect(...) 这些函数说明如何为index_merge联接类型合并索引扫描。详细信息参见7.2.6节,“索引合并优化”。
o Using index for group-by 相似于访问表的Using index方式,Using index for group-by表示MySQL发现了一个索引,能够用来查询GROUP BY或DISTINCT查询的全部列,而不要额外搜索硬盘访问实际的表。而且,按最有效的方式使用索引,以便对于每一个组,只读取少许索引条目。详情参见7.2.13节,“MySQL如何优化GROUP BY”。
经过相乘EXPLAIN输出的rows列的全部值,你能获得一个关于一个联接如何的提示。这应该粗略地告诉你MySQL必须检查多少行以执行查询。当你使用max_join_size变量限制查询时,也用这个乘积来肯定执行哪一个多表SELECT语句。参见7.5.2节,“调节服务器参数”。
MySQL执行计划的局限
• EXPLAIN不会告诉你关于触发器、存储过程的信息或用户自定义函数对查询的影响状况
• EXPLAIN不考虑各类Cache
• EXPLAIN不能显示MySQL在执行查询时所做的优化工做
• 部分统计信息是估算的,并不是精确值
• EXPALIN只能解释SELECT操做,其余操做要重写为SELECT后查看执行计划
相关表:
mysql> show create table student\G;
*************************** 1. row ***************************
Table: student
Create Table: CREATE TABLE `student` (
`id` int(11) NOT NULL DEFAULT '0',
`sname` varchar(20) DEFAULT NULL,
`sex` varchar(2) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk
1 row in set (0.00 sec)
ERROR:
No query specified
mysql> show create table course\G;
*************************** 1. row ***************************
Table: course
Create Table: CREATE TABLE `course` (
`id` int(11) NOT NULL DEFAULT '0',
`cname` varchar(20) DEFAULT NULL,
`tid` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `tid` (`tid`),
CONSTRAINT `course_ibfk_1` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk
1 row in set (0.00 sec)
ERROR:
No query specified
mysql> show create table sc\G;
*************************** 1. row ***************************
Table: sc
Create Table: CREATE TABLE `sc` (
`sid` int(11) DEFAULT NULL,
`cid` int(11) DEFAULT NULL,
`score` int(11) DEFAULT NULL,
KEY `sid` (`sid`),
KEY `cid` (`cid`),
CONSTRAINT `sc_ibfk_1` FOREIGN KEY (`sid`) REFERENCES `student` (`id`),
CONSTRAINT `sc_ibfk_2` FOREIGN KEY (`cid`) REFERENCES `course` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk
1 row in set (0.00 sec)
ERROR:
No query specified
mysql> show create table teacher\G;
*************************** 1. row ***************************
Table: teacher
Create Table: CREATE TABLE `teacher` (
`id` int(11) NOT NULL DEFAULT '0',
`tname` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `tname` (`tname`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk
1 row in set (0.00 sec)
ERROR:
No query specified
mysql> alter table teacher add unique(tname);
insert into teacher values(2010, 'wang');
insert into course values(1011, 'english', 2010);