查询执行计划(Explain)
<ul>
<li>在5.6以及以后的版本中,除过select,其他比如insert,update和delete均可以使用explain查看执行计划,从而知道mysql是如何处理sql语句,分析查询语句或者表结构的性能瓶颈。</li>
</ul>
<pre><code class="language-mysql"># 完整写法
EXPLAIN [ explain_type] { explainable_stmt }
explain_type: { EXTENDED | PARTITIONS | FORMAT = format_name}
format_name: { TRADITIONAL | JSON}
explainable_stmt: { SELECT statement | DELETE statement | INSERT statement | REPLACE statement | UPDATE statement }
# 简单写法
EXPLAIN tbl_name
或:
EXPLAIN [EXTENDED] SELECT select_options</code></pre>
<h2>普通</h2>
<pre><code class="language-mysql">explain select * from subject where id = 1; </code></pre>
<h3>结果列说明</h3>
<table>
<thead>
<tr>
<th>输出列</th>
<th>名称</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>id</td>
<td>查询标识</td>
<td>包含一组数字,查询中执行 select 子句或操作表的顺序</td>
</tr>
<tr>
<td>select_type</td>
<td>查询类型</td>
<td></td>
</tr>
<tr>
<td>table</td>
<td>查询涉及的表</td>
<td></td>
</tr>
<tr>
<td>partitions</td>
<td>匹配到的分区信息</td>
<td>对于非分区表,值为 NULL</td>
</tr>
<tr>
<td>type</td>
<td>连接类型(访问类型)</td>
<td></td>
</tr>
<tr>
<td>possible_keys</td>
<td>可能选择的索引</td>
<td>能应用在这张表中的索引,一个或多个,<br />但不一定实际使用到</td>
</tr>
<tr>
<td>key</td>
<td>实际使用的索引</td>
<td>如果为 NULL,则没有使用索引<br />查询中若使用了覆盖索引(查询的列刚好是索引),<br />则该索引仅出现在key列表</td>
</tr>
<tr>
<td>key_len</td>
<td>实际使用的索引的长度</td>
<td>索引中使用的字节数,<br />可通过该列计算查询中使用的索引的长度</td>
</tr>
<tr>
<td>ref</td>
<td>和索引进行比较的列</td>
<td>显示索引的哪一列被使用,<br />列或常量被用于查找索引列上的值</td>
</tr>
<tr>
<td>rows</td>
<td>需要被检索的大致行数</td>
<td>大致估算出找到所需的记录所需读取的行数</td>
</tr>
<tr>
<td>filtered</td>
<td>按表条件过滤的行百分比</td>
<td></td>
</tr>
<tr>
<td>Extra</td>
<td>额外信息</td>
<td>包含不适合在其它列中显示,但十分重要的额外信息</td>
</tr>
</tbody>
</table>
<h2>查询标识(id)</h2>
<ul>
<li>id 相同
<ul>
<li>执行顺序从上至下</li>
</ul></li>
<li>id 不相同
<ul>
<li>如果是子查询,id 的序号会递增,id 的值越大,优先级越高,越先被执行</li>
</ul></li>
<li>id 相同又不相同
<ul>
<li>id 如果相同,是一组从上往下顺执行。</li>
<li>在所有组中,id 值越大,优先级越高,越先执行</li>
</ul></li>
</ul>
<h2>查询类型(select_type)</h2>
<table>
<thead>
<tr>
<th>查询类型</th>
<th>查询类型</th>
<th>含义</th>
</tr>
</thead>
<tbody>
<tr>
<td>SIMPLE</td>
<td>simple</td>
<td>简单查询(不包含子查询或 UNION )</td>
</tr>
<tr>
<td>PRIMARY</td>
<td>primary</td>
<td>最外层查询</td>
</tr>
<tr>
<td>UNION</td>
<td>union</td>
<td>UNION 语句中第二或更后面的查询</td>
</tr>
<tr>
<td>DEPENDENT UNION</td>
<td>dependent union</td>
<td>依赖外部查询的 UNION 中第二或更后面的查询</td>
</tr>
<tr>
<td>UNION RESULT</td>
<td>union result</td>
<td>UNION 语句的结果集</td>
</tr>
<tr>
<td>SUBQUERY</td>
<td>subquery</td>
<td>子查询中的第一个查询</td>
</tr>
<tr>
<td>DEPENDENT SUBQUERY</td>
<td>dependent subquery</td>
<td>依赖外部查询的子查询中的第一个查询</td>
</tr>
<tr>
<td>DERIVED</td>
<td>derived</td>
<td>查询的派生表(在 FROM 从句中的子查询)</td>
</tr>
<tr>
<td>MATERIALIZED</td>
<td>materialized</td>
<td>物化子查询</td>
</tr>
<tr>
<td>UNCACHEABLE SUBQUERY</td>
<td>uncacheable subquery</td>
<td>无法缓存结果的子查询<br />并且必须为外部查询的每一行重新计算</td>
</tr>
<tr>
<td>UNCACHEABLE UNION</td>
<td>uncacheable union</td>
<td>属于无法缓存的子查询的 UNION 的第二或更后面的查询</td>
</tr>
</tbody>
</table>
<h2>查询涉及的表(table )</h2>
<ul>
<li>< unionM,N>
<ul>
<li>输出行引用了id值为M和N的行的UNION结果。 </li>
</ul></li>
<li>
< derivedN>
- 该行引用了一个id值为n的行的派生表结果。
- 例如,派生表可以从from子句的子查询中得到结果。
</li>
<li>
< subqueryN>
- 输出行引用了id值为N的行的物化子查询的结果
</li>
</ul>
<h2>连接类型(访问类型)type</h2>
<ul>
<li>常见类型从最好到最差依次如下:</li>
<li>NULL -> system -> const -> eq_ref -> ref -> fulltext -> ref_or_null -> index_merge -> unique_subquery -> index_subquery -> range -> index -> ALL</li>
</ul>
<h2>key_len</h2>
<ul>
<li>表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度</li>
<li>在不损失精确度的情况下,长度越短越好</li>
<li>key_len显示的值为索引字段最大的可能长度,并非实际使用长度
即key_len是根据定义计算而得,不是通过表内检索出的</li>
</ul>
<h2>json格式</h2>
<pre><code class="language-mysql">explain format=json select * from subject where id = 1; # json格式</code></pre>
<h2>参考网址</h2>
<ul>
<li>
<p>MySQL Explain 详解</p>
<ul>
<li><a href="https://blog.csdn.net/tianya9704/article/details/80067860">https://blog.csdn.net/tianya9704/article/details/80067860</a></li>
</ul>
</li>
<li>一张图彻底搞懂MySQL的 explain
<ul>
<li><a href="https://segmentfault.com/a/1190000021458117?utm_source=tag-newest">https://segmentfault.com/a/1190000021458117?utm_source=tag-newest</a></li>
</ul></li>
</ul>