(1)子查询的执行计划
    EXPLAIN SELECT FROM t1 WHERE x1 *IN (SELECT x1 FROM t2) OR x3=’xxx’
    这个SQL稍微有点复杂,因为主SELECT语句的WHERE筛选条件是依赖于下一个子查询的,而且除此之外还有一个自己的WHERE筛选条件,看看执行计划:

    1. +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-------------+
    2. | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
    3. +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-------------+
    4. | 1 | PRIMARY | t1 | NULL | ALL | index_x3 | NULL | NULL | NULL | 3457 | 100.00 | Using where |
    5. +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-------------+
    6. | 2 | SUBQUERY | t2 | NULL | index | index_x1 | index_x1 | 507 | NULL | 4687 | 100.00 | Using index |
    7. +----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-------------+

    首先第一条执行计划的id是1,第二条执行计划的id是2,这是为什么?因为在这个SQL里有两个SELECT,主查询SELECT的执行计划的id就是1,子查询SELECT的执行计划的id就是2。
    其次,第一条执行计划里,select_type是PRIMARY,不是SIMPLE,说明第一个执行计划的查询类型是主查询类型的意思,对主查询而言,他有一个where条件x3=’xxx’,所以他的possible_key里包含了index_x3,就是x3字段的索引,但是他的key实际是NULL,而type是ALL,所以说最后没选择用x3字段的索引,而是选择全表扫描。
    这个是为什么?其实很简单,可能他通过成本分析发现,使用x3字段的索引扫描xxx这个值,几乎跟全表扫描差不多,可能x3这个字段的值几乎都是xxx,所以最后还不如全表扫描。
    接着第二条执行计划,他的select_type是SUBQUERY,也就是子查询,子查询针对的是t2这个表,当然子查询本身就是一个全表查询,但是对主查询而言,会使用x1 in这个筛选条件,他这里type是index,说明使用了扫描index_x1这个x1字段的二级索引的方式,直接扫描x1字段的二级索引,来跟子查询结果集做比对。

    (2)UNION的执行计划
    EXPLAIN SELECT FROM t1 UNION SELECT FROM t2
    这是一个典型的union语句,把两个表的查询结果合并起来

    1. +----+--------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
    2. | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
    3. +----+--------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
    4. | 1 | PRIMARY | t1 | NULL | ALL | NULL | NULL | NULL | NULL | 3457 | 100.00 | NULL |
    5. | 2 | UNION | t2 | NULL | ALL | NULL | NULL | NULL | NULL | 4687 | 100.00 | NULL |
    6. | NULL | UNION RESULT | <union1,2> | NULL | ALL | NULL | NULL | NULL | NULL | NULL | NULL | Using temporary |
    7. +----+--------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+

    这个执行计划的第一条和第二条很好理解,两个SELECT语句对应id,就是分别从t1表和t2表里进行全表扫描,接着就是第三条执行计划,其实union字句默认的作用就是把两个结果集合并起来还会进行去重,所以第三个执行计划是去重。
    所以上面的table ,这就是一个临时表的表名,而且extra里,是Using temporary,也就是使用临时表的意思,就是把结果集放到临时表里去重的,就是这个意思。当然如果用的是union all,那就不会进行去重了。

    Using join buffer , Using Where,Using temporary, Extra列信息显示这些信息SQL性能执行都比较差