MySql提供了EXPLAIN语法用来进行查询分析，在SQL语句前加一个"EXPLAIN"即可。比如我们要分析如下SQL语句：

**explain** select * from table where table.id = 1

运行上面的sql语句后你会看到，下面的表头信息：
table | type | possible_keys | key | key_len | ref | rows | Extra

EXPLAIN列的解释
id
id主要是用来标识sql执行顺序，如果没有子查询，一般来说id只有1个，执行顺序也是从上到下。

**SELECT_TYPE**
这一列显示了对应行是简单还是复杂SELECT.取值如下:SIMPLE值意味着查询不包括子查询和UNION。查询有任何复杂的子部分，则最外层标记为PRIMARY.取值如下：
  1. SIMPLE：不包含子查询或是UNION操作的查询
  2. PRIMARY:查询中包含了任何复杂的子部分，最外层的就会变成PRIMARY
  3. SUBQUERY:在SELECT或者WHERE列表中包含了子查询
  4. DERIVED：在FROM中包含了子查询
  5. UNION:如果第二个SELECT出现在UNION之后，则被标记为UNION，如果UNION包含在FROM子句的子查询中，外层SELECT会被标记为：DERIVED   
  6. UNION RESULT从UNION表获取结果的select


**table**
显示这一行的数据是关于哪张表的
**type**
这是重要的列，显示连接使用了何种类型。从最好到最差的连接类型为const、eq_reg、ref、range、indexhe和ALL （按照效率高低的顺序排序）
  1. system：表只有一行：system表。这是const连接类型的特殊情况。
  2. const ：表中的一个记录的最大值能够匹配这个查询（索引可以是主键或惟一索引）。因为只有一行，这个值实际就是常数，因为MYSQL先读这个值然后把它当做常数来对待。
  3. eq_ref：在连接中，MYSQL在查询时，从前面的表中，对每一个记录的联合都从表中读取一个记录，它在查询使用了索引为主键或惟一键的全部时使用。
  4. ref：这个连接类型只有在查询使用了不是惟一或主键的键或者是这些类型的部分（比如，利用最左边前缀）时发生。对于之前的表的每一个行联合，全部记录都将从表中读出。这个类型严重依赖于根据索引匹配的记录多少—越少越好。
  5. range：这个连接类型使用索引返回一个范围中的行，比如使用>或<查找东西时发生的情况。
  6. index：这个连接类型对前面的表中的每一个记录联合进行完全扫描（比ALL更好，因为索引一般小于表数据）。
  7. ALL：这个连接类型对于前面的每一个记录联合进行完全扫描，这一般比较糟糕，应该尽量避免。
**possible_keys**
显示可能应用在这张表中的索引。如果为空，没有可能的索引。可以为相关的域从WHERE语句中选择一个合适的语句
**key**
实际使用的索引。如果为NULL，则没有使用索引。很少的情况下，MYSQL会选择优化不足的索引。这种情况下，可以在SELECT语句中使用USE INDEX（indexname）来强制使用一个索引或者用IGNORE INDEX（indexname）来强制MYSQL忽略索引
**key_len**
使用的索引的长度。在不损失精确性的情况下，长度越短越好
**ref**
显示索引的哪一列被使用了，如果可能的话，是一个常数
**rows**
MYSQL认为必须检查的用来返回请求数据的行数
**Extra**
关于MYSQL如何解析查询的额外信息。将在表4.3中讨论，但这里可以看到的坏的例子是Using temporary和Using filesort，意思MYSQL根本不能使用索引，结果是检索会很慢
说明：extra列返回的描述的意义
  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，这就会发生，或者是查询有问题。

因此，弄明白了explain语法返回的每一项结果，我们就能知道查询大致的运行时间了，如果查询里没有用到索引、或者需要扫描的行过多，那么可以感到明显的延迟。因此需要改变查询方式或者新建索引。mysql中的explain语法可以帮助我们改写查询，优化表的结构和索引的设置，从而最大地提高查询效率。当然，在大规模数据量时，索引的建立和维护的代价也是很高的，往往需要较长的时间和较大的空间，如果在不同的列组合上建立索引，空间的开销会更大。因此索引最好设置在需要经常查询的字段中。
