子查询优化

子查询优化

测试版本:
percona server 5.6.19-67.0-log Percona Server (GPL), Release 67.0, Revision 618
mariadb 10.0.12-MariaDB-log MariaDB Server

总结:
1、mysql不支持子查询合并和聚合函数子查询优化,mariadb对聚合函数子查询进行物化优化;
2、mysql不支持from子句子查询优化,mariadb对from子句子查询进行子查询上拉优化;
3、mysql和mariadb对子查询展开提供有限的支持,如对主键的操作才能进行上拉子查询优化;
4、mysql不支持exists子查询优化,mariadb对exists关联子查询进行半连接优化,对exists非关联子查询没有进一步进行优化;
5、mysql和mariadb不支持not exists子查询优化;
6、mysql和mariadb对in子查询,对满足半连接语义的查询进行半连接优化,再基于代价评估进行优化,两者对半连接的代价评估选择方式有差异;
7、mysql不支持not in子查询优化,mariadb对非关联not in子查询使用物化优化,对关联not in子查询不做优化;
8、mysql和mariadb对>all非关联子查询使用max函数,<all非关联子查询使用min函数,对=all和非关联子查询使用exists优化;
9、对>some和>any非关联子查询使用min函数,对<some和<any非关联子查询使用max函数,=any和=some子查询使用半连接进行优化,对>some和>any关联子查询以及<some和<any关联子查询只有exists优化。

1、子查询合并,内部不支持
root@[test] 10:37:57>explain format=json select * from t1 where a1<4 and (exists (select a2 from t2 where t2.a2 < 5 and t2.b2 = 2) or exists (select a2 from t2 where t2.a2 < 5 and t2.b2=2))\G;
*************************** 1. row ***************************
EXPLAIN: {
  "query_block": {
    "select_id": 1,
    "table": {
      "message": "Impossible WHERE"
    },
    "optimized_away_subqueries": [
      {
        "dependent": false,
        "cacheable": true,
        "query_block": {
          "select_id": 3,
          "table": {
            "table_name": "t2",
            "access_type": "range",
            "possible_keys": [
              "t_idx_t2"
            ],
            "key": "t_idx_t2",
            "used_key_parts": [
              "a2"
            ],
            "key_length": "5",
            "rows": 3,
            "filtered": 100,
            "index_condition": "(`test`.`t2`.`a2` < 5)",
            "attached_condition": "(`test`.`t2`.`b2` = 2)"
          }
        }
      },
      {
        "dependent": false,
        "cacheable": true,
        "query_block": {
          "select_id": 2,
          "table": {
            "table_name": "t2",
            "access_type": "range",
            "possible_keys": [
              "t_idx_t2"
            ],
            "key": "t_idx_t2",
            "used_key_parts": [
              "a2"
            ],
            "key_length": "5",
            "rows": 3,
            "filtered": 100,
            "index_condition": "(`test`.`t2`.`a2` < 5)",
            "attached_condition": "(`test`.`t2`.`b2` = 2)"
          }
        }
      }
    ]
  }
}
1 row in set, 1 warning (0.00 sec)

mariadb 10.0.2:
root@[test] 10:38:40>explain extended select * from t1 where a1<4 and (exists (select a2 from t2 where t2.a2 < 5 and t2.b2 = 2) or exists (select a2 from t2 where t2.a2 < 5 and t2.b2=2));
+------+-------------+-------+-------+---------------+----------+---------+------+------+----------+------------------------------------+
| id   | select_type | table | type  | possible_keys | key      | key_len | ref  | rows | filtered | Extra                              |
+------+-------------+-------+-------+---------------+----------+---------+------+------+----------+------------------------------------+
|    1 | PRIMARY     | NULL  | NULL  | NULL          | NULL     | NULL    | NULL | NULL |     NULL | Impossible WHERE                   |
|    3 | SUBQUERY    | t2    | range | t_idx_t2      | t_idx_t2 | 5       | NULL |    3 |   100.00 | Using index condition; Using where |
|    2 | SUBQUERY    | t2    | range | t_idx_t2      | t_idx_t2 | 5       | NULL |    3 |   100.00 | Using index condition; Using where |
+------+-------------+-------+-------+---------------+----------+---------+------+------+----------+------------------------------------+
3 rows in set, 1 warning (0.00 sec)

root@[test] 10:38:46>show warnings;
+-------+------+-----------------------------------------------------------------------------------+
| Level | Code | Message                                                                           |
+-------+------+-----------------------------------------------------------------------------------+
| Note  | 1003 | select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where 0 |
+-------+------+-----------------------------------------------------------------------------------+
1 row in set (0.00 sec)

两条子查询都是独立执行,没有进行子查询合并操作。

手工合并后:只进行一次子查询扫描
root@[test] 18:46:32>explain extended select * from t1 where a1<4 and (exists (select a2 from t2 where t2.a2 < 5 and (t2.b2 = 1 or t2.b2 =3)));
+----+-------------+-------+-------+---------------+----------+---------+------+------+----------+-------------+
| id | select_type | table | type  | possible_keys | key      | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+-------+---------------+----------+---------+------+------+----------+-------------+
|  1 | PRIMARY     | t1    | range | t_idx_t1      | t_idx_t1 | 5       | NULL |    2 |   100.00 | Using where |
|  2 | SUBQUERY    | t2    | range | t_idx_t2      | t_idx_t2 | 5       | NULL |    3 |   100.00 | Using where |
+----+-------------+-------+-------+---------------+----------+---------+------+------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)

root@[test] 18:49:26>show warnings;
+-------+------+--------------------------------------------------------------------------------------------------------+
| Level | Code | Message                                                                                                |
+-------+------+--------------------------------------------------------------------------------------------------------+
| Note  | 1003 | select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where (`test`.`t1`.`a1` < 4) |
+-------+------+--------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

在t2上只执行了一次扫描

2、子查询反嵌套(子查询展开)
子查询在from子句:
root@[test] 10:54:44>explain extended select * from t1,(select * from t2 where t2.a2 > 10) v_t2 where t1.a1 < 10 and v_t2.a2<20;
+----+-------------+------------+-------+---------------+----------+---------+------+-------+----------+----------------------------------------------
| id | select_type | table      | type  | possible_keys | key      | key_len | ref  | rows  | filtered | Extra                                              |
+----+-------------+------------+-------+---------------+----------+---------+------+-------+----------+----------------------------------------------
|  1 | PRIMARY     | t1         | range | t_idx_t1      | t_idx_t1 | 5       | NULL |     8 |   100.00 | Using index condition                              |
|  1 | PRIMARY     | <derived2> | ALL   | NULL          | NULL     | NULL    | NULL |  5078 |   100.00 | Using where; Using join buffer (Block Nested Loop) |
|  2 | DERIVED     | t2         | ALL   | t_idx_t2      | NULL     | NULL    | NULL | 10157 |    50.00 | Using where                                        |
+----+-------------+------------+-------+---------------+----------+---------+------+-------+----------+----------------------------------------------
3 rows in set, 1 warning (0.00 sec)

root@[test] 10:58:20>show warnings;
+-------+------+--------------------------------------------------------------------------------------------------------------------------------------
| Level | Code | Message
+-------+------+--------------------------------------------------------------------------------------------------------------------------------------
| Note  | 1003 | /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1`,`v_t2`.`a2` AS `a2`,`v_t2`.`b2` AS `b2` from `test`.`t1` join (/* select#2 */ select `test`.`t2`.`a2` AS `a2`,`test`.`t2`.`b2` AS `b2` from `test`.`t2` where (`test`.`t2`.`a2` > 10)) `v_t2` where ((`test`.`t1`.`a1` < 10) and (`v_t2`.`a2` < 20)) |
+-------+------+--------------------------------------------------------------------------------------------------------------------------------------
1 row in set (0.00 sec)

子查询单独执行,子查询没有消除

mariadb 10.0.2:
root@[test] 10:54:54>explain extended select * from t1,(select * from t2 where t2.a2 > 10) v_t2 where t1.a1 < 10 and v_t2.a2<20;
+------+-------------+-------+-------+---------------+----------+---------+------+------+----------+--------------------------------------------------
| id   | select_type | table | type  | possible_keys | key      | key_len | ref  | rows | filtered | Extra                                                                  |
+------+-------------+-------+-------+---------------+----------+---------+------+------+----------+--------------------------------------------------
|    1 | SIMPLE      | t1    | range | t_idx_t1      | t_idx_t1 | 5       | NULL |    8 |   100.00 | Using index condition                                                  |
|    1 | SIMPLE      | t2    | range | t_idx_t2      | t_idx_t2 | 5       | NULL |    8 |   100.00 | Using index condition; Using where; Using join buffer (flat, BNL join) |
+------+-------------+-------+-------+---------------+----------+---------+------+------+----------+--------------------------------------------------
2 rows in set, 1 warning (0.00 sec)

root@[test] 10:58:18>show warnings;
+-------+------+--------------------------------------------------------------------------------------------------------------------------------------
| Level | Code | Message
+-------+------+--------------------------------------------------------------------------------------------------------------------------------------
| Note  | 1003 | select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1`,`test`.`t2`.`a2` AS `a2`,`test`.`t2`.`b2` AS `b2` from `test`.`t1` join `test`.`t2` where ((`test`.`t1`.`a1` < 10) and (`test`.`t2`.`a2` < 20) and (`test`.`t2`.`a2` > 10)) |
+-------+------+--------------------------------------------------------------------------------------------------------------------------------------
1 row in set (0.00 sec)

而mariadb对该查询进行优化,将子查询上拉,条件下推到了外层查询where条件中。

in子查询:
root@[test] 11:04:32>explain extended select * from t1 where t1.a1<100 and a1 in (select a2 from t2 where t2.a2>10);
+----+-------------+-------+-------+---------------+----------+---------+------------+------+----------+-------------------------------------------+
| id | select_type | table | type  | possible_keys | key      | key_len | ref        | rows | filtered | Extra                                     |
+----+-------------+-------+-------+---------------+----------+---------+------------+------+----------+-------------------------------------------+
|  1 | SIMPLE      | t2    | range | t_idx_t2      | t_idx_t2 | 5       | NULL       |   88 |   100.00 | Using where; Using index; Start temporary |
|  1 | SIMPLE      | t1    | ref   | t_idx_t1      | t_idx_t1 | 5       | test.t2.a2 |    1 |   100.00 | End temporary                             |
+----+-------------+-------+-------+---------------+----------+---------+------------+------+----------+-------------------------------------------+
2 rows in set, 1 warning (0.00 sec)

root@[test] 11:07:13>show warnings;
+-------+------+--------------------------------------------------------------------------------------------------------------------------------------
| Level | Code | Message
+-------+------+--------------------------------------------------------------------------------------------------------------------------------------
| Note  | 1003 | /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t1`.`a1` = `test`.`t2`.`a2`) and (`test`.`t2`.`a2` < 100) and (`test`.`t2`.`a2` > 10)) |
+-------+------+--------------------------------------------------------------------------------------------------------------------------------------
1 row in set (0.00 sec)

修改条件:
root@[test] 11:31:25>explain extended select * from t1 where t1.a1<100 and a1 in (select a2 from t2 where t2.a2<10);
+----+--------------+-------------+--------+---------------+------------+---------+------------+------+----------+--------------------------+
| id | select_type  | table       | type   | possible_keys | key        | key_len | ref        | rows | filtered | Extra                    |
+----+--------------+-------------+--------+---------------+------------+---------+------------+------+----------+--------------------------+
|  1 | SIMPLE       | t1          | ALL    | t_idx_t1      | NULL       | NULL    | NULL       |   13 |    61.54 | Using where              |
|  1 | SIMPLE       | <subquery2> | eq_ref | <auto_key>    | <auto_key> | 5       | test.t1.a1 |    1 |   100.00 | NULL                     |
|  2 | MATERIALIZED | t2          | range  | t_idx_t2      | t_idx_t2   | 5       | NULL       |    8 |   100.00 | Using where; Using index |
+----+--------------+-------------+--------+---------------+------------+---------+------------+------+----------+--------------------------+
3 rows in set, 1 warning (0.00 sec)

root@[test] 11:31:26>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` semi join (`test`.`t2`) where ((`<subquery2>`.`a2` = `test`.`t1`.`a1`) and (`test`.`t1`.`a1` < 100) and (`test`.`t2`.`a2` < 10))
1 row in set (0.00 sec)

ERROR: 
No query specified
子查询被物化或单独执行,没有上拉。

添加主键:默认使用Innodb内建的主键
root@[test] 11:07:14>alter table t1 add primary key(a1);
Query OK, 10000 rows affected (0.07 sec)
Records: 10000  Duplicates: 0  Warnings: 0

root@[test] 11:10:41>alter table t2 add primary key(a2);
Query OK, 10000 rows affected (0.07 sec)
Records: 10000  Duplicates: 0  Warnings: 0

root@[test] 11:10:54>alter table t3 add primary key(a3);
Query OK, 10000 rows affected (0.08 sec)
Records: 10000  Duplicates: 0  Warnings: 0

root@[test] 11:10:59>explain extended select * from t1 where t1.a1<100 and a1 in (select a2 from t2 where t2.a2>10);
+----+-------------+-------+--------+------------------+---------+---------+------------+------+----------+-------------+
| id | select_type | table | type   | possible_keys    | key     | key_len | ref        | rows | filtered | Extra       |
+----+-------------+-------+--------+------------------+---------+---------+------------+------+----------+-------------+
|  1 | SIMPLE      | t1    | range  | PRIMARY,t_idx_t1 | PRIMARY | 4       | NULL       |   88 |   100.00 | Using where |
|  1 | SIMPLE      | t2    | eq_ref | PRIMARY,t_idx_t2 | PRIMARY | 4       | test.t1.a1 |    1 |   100.00 | Using index |
+----+-------------+-------+--------+------------------+---------+---------+------------+------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)

root@[test] 11:12:24>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t2` join `test`.`t1` where ((`test`.`t2`.`a2` = `test`.`t1`.`a1`) and (`test`.`t1`.`a1` < 100) and (`test`.`t1`.`a1` > 10))
1 row in set (0.00 sec)

ERROR: 
No query specified

只有当子查询是针对主键列时,才能把子查询上拉为内连接。

mariadb 10.0.2:
root@[test] 11:04:29>explain extended select * from t1 where t1.a1<100 and a1 in (select a2 from t2 where t2.a2>10);
+------+--------------+-------------+--------+---------------+--------------+---------+------+------+----------+--------------------------+
| id   | select_type  | table       | type   | possible_keys | key          | key_len | ref  | rows | filtered | Extra                    |
+------+--------------+-------------+--------+---------------+--------------+---------+------+------+----------+--------------------------+
|    1 | PRIMARY      | t1          | range  | t_idx_t1      | t_idx_t1     | 5       | NULL |   88 |   100.00 | Using index condition    |
|    1 | PRIMARY      | <subquery2> | eq_ref | distinct_key  | distinct_key | 4       | func |    1 |   100.00 |                          |
|    2 | MATERIALIZED | t2          | range  | t_idx_t2      | t_idx_t2     | 5       | NULL |   88 |   100.00 | Using where; Using index |
+------+--------------+-------------+--------+---------------+--------------+---------+------+------+----------+--------------------------+
3 rows in set, 1 warning (0.00 sec)

root@[test] 11:07:08>show warnings;
+-------+------+--------------------------------------------------------------------------------------------------------------------------------------
| Level | Code | Message
+-------+------+--------------------------------------------------------------------------------------------------------------------------------------
| Note  | 1003 | select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t1`.`a1` < 100) and (`test`.`t2`.`a2` > 10)) |
+-------+------+--------------------------------------------------------------------------------------------------------------------------------------
1 row in set (0.00 sec)

root@[test] 11:10:08>alter table t1 add primary key(a1);
Query OK, 10000 rows affected (0.07 sec)               
Records: 10000  Duplicates: 0  Warnings: 0

root@[test] 11:10:11>alter table t2 add primary key(a2);
Query OK, 10000 rows affected (0.07 sec)               
Records: 10000  Duplicates: 0  Warnings: 0

root@[test] 11:10:21>alter table t3 add primary key(a3);
Query OK, 10000 rows affected (0.07 sec)               
Records: 10000  Duplicates: 0  Warnings: 0

root@[test] 11:10:26>desc t1;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| a1    | int(11) | NO   | PRI | 0       |       |
| b1    | int(11) | YES  |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
2 rows in set (0.00 sec)

root@[test] 11:10:32>explain extended select * from t1 where t1.a1<100 and a1 in (select a2 from t2 where t2.a2>10);
+------+-------------+-------+--------+------------------+---------+---------+------------+------+----------+-------------+
| id   | select_type | table | type   | possible_keys    | key     | key_len | ref        | rows | filtered | Extra       |
+------+-------------+-------+--------+------------------+---------+---------+------------+------+----------+-------------+
|    1 | PRIMARY     | t1    | range  | PRIMARY,t_idx_t1 | PRIMARY | 4       | NULL       |   88 |   100.00 | Using where |
|    1 | PRIMARY     | t2    | eq_ref | PRIMARY,t_idx_t2 | PRIMARY | 4       | test.t1.a1 |    1 |   100.00 | Using index |
+------+-------------+-------+--------+------------------+---------+---------+------------+------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)

root@[test] 11:12:00>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t2` join `test`.`t1` where ((`test`.`t2`.`a2` = `test`.`t1`.`a1`) and (`test`.`t1`.`a1` < 100) and (`test`.`t1`.`a1` > 10))
1 row in set (0.00 sec)

ERROR: No query specified

mariadb也类似,但是mariadb在子查询返回表的99%行(总共10000行,返回9990行)时也进行了物化,而mysql单独执行子查询,使用临时表。

3、聚集子查询消除,内部不支持
root@[test] 11:40:42>explain extended select * from t1 where t1.a1>(select min(t2.a2) from t2);
+----+-------------+-------+------+---------------+------+---------+------+-------+----------+------------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra                        |
+----+-------------+-------+------+---------------+------+---------+------+-------+----------+------------------------------+
|  1 | PRIMARY     | t1    | ALL  | t_idx_t1      | NULL | NULL    | NULL | 10157 |    50.00 | Using where                  |
|  2 | SUBQUERY    | NULL  | NULL | NULL          | NULL | NULL    | NULL |  NULL |     NULL | Select tables optimized away |
+----+-------------+-------+------+---------------+------+---------+------+-------+----------+------------------------------+
2 rows in set, 1 warning (0.00 sec)

root@[test] 11:40:46>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where (`test`.`t1`.`a1` > (/* select#2 */ select min(`test`.`t2`.`a2`) from `test`.`t2`))
1 row in set (0.00 sec)

ERROR: 
No query specified

mariadb 10.0.2:
root@[test] 11:46:47>explain extended select * from t1 where t1.a1>(select min(t2.a2) from t2);
+------+-------------+-------+------+---------------+------+---------+------+-------+----------+------------------------------+
| id   | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra                        |
+------+-------------+-------+------+---------------+------+---------+------+-------+----------+------------------------------+
|    1 | PRIMARY     | t1    | ALL  | t_idx_t1      | NULL | NULL    | NULL | 10157 |    50.00 | Using where                  |
|    2 | SUBQUERY    | NULL  | NULL | NULL          | NULL | NULL    | NULL |  NULL |     NULL | Select tables optimized away |
+------+-------------+-------+------+---------------+------+---------+------+-------+----------+------------------------------+
2 rows in set, 1 warning (0.00 sec)

root@[test] 11:46:48>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where (`test`.`t1`.`a1` > (select min(`test`.`t2`.`a2`) from `test`.`t2`))
1 row in set (0.00 sec)

ERROR: No query specified

子查询存在,没有消除。

聚合函数子查询在in条件中:
root@[test] 11:40:48>explain extended select * from t1 where t1.a1 in (select min(t2.a2) from t2);
+----+--------------------+-------+------+---------------+------+---------+------+-------+----------+------------------------------+
| id | select_type        | table | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra                        |
+----+--------------------+-------+------+---------------+------+---------+------+-------+----------+------------------------------+
|  1 | PRIMARY            | t1    | ALL  | NULL          | NULL | NULL    | NULL | 10157 |   100.00 | Using where                  |
|  2 | DEPENDENT SUBQUERY | NULL  | NULL | NULL          | NULL | NULL    | NULL |  NULL |     NULL | Select tables optimized away |
+----+--------------------+-------+------+---------------+------+---------+------+-------+----------+------------------------------+
2 rows in set, 1 warning (0.00 sec)

root@[test] 11:50:54>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where <in_optimizer>(`test`.`t1`.`a1`,<exists>(/* select#2 */ select min(`test`.`t2`.`a2`) from `test`.`t2` having (<cache>(`test`.`t1`.`a1`) = <ref_null_helper>(min(`test`.`t2`.`a2`)))))
1 row in set (0.00 sec)

ERROR: 
No query specified

mariadb 10.0.2:
root@[test] 11:50:16>explain extended select * from t1 where t1.a1 in (select min(t2.a2) from t2);
+------+--------------+-------------+--------+---------------+----------+---------+-------+------+----------+------------------------------+
| id   | select_type  | table       | type   | possible_keys | key      | key_len | ref   | rows | filtered | Extra                        |
+------+--------------+-------------+--------+---------------+----------+---------+-------+------+----------+------------------------------+
|    1 | PRIMARY      | <subquery2> | system | NULL          | NULL     | NULL    | NULL  |    1 |   100.00 |                              |
|    1 | PRIMARY      | t1          | ref    | t_idx_t1      | t_idx_t1 | 5       | const |    1 |   100.00 | Using index condition        |
|    2 | MATERIALIZED | NULL        | NULL   | NULL          | NULL     | NULL    | NULL  | NULL |     NULL | Select tables optimized away |
+------+--------------+-------------+--------+---------------+----------+---------+-------+------+----------+------------------------------+
3 rows in set, 1 warning (0.00 sec)

root@[test] 11:50:42>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where (`test`.`t1`.`a1` = <cache>(1))
1 row in set (0.00 sec)

ERROR: No query specified

子查询存在,没有消除。mariadb进行物化优化。

4、特殊格式子查询
包括IN、ALL、ANY、SOME、EXISTS等类型的子查询
EXISTS子查询:相关子查询
root@[test] 12:03:23>explain extended select * from t1 where exists(select 1 from t2 where t1.a1=t2.a2 and t2.a2>10);
+----+--------------------+-------+------+---------------+----------+---------+------------+-------+----------+--------------------------+
| id | select_type        | table | type | possible_keys | key      | key_len | ref        | rows  | filtered | Extra                    |
+----+--------------------+-------+------+---------------+----------+---------+------------+-------+----------+--------------------------+
|  1 | PRIMARY            | t1    | ALL  | NULL          | NULL     | NULL    | NULL       | 10157 |   100.00 | Using where              |
|  2 | DEPENDENT SUBQUERY | t2    | ref  | t_idx_t2      | t_idx_t2 | 5       | test.t1.a1 |     1 |   100.00 | Using where; Using index |
+----+--------------------+-------+------+---------------+----------+---------+------------+-------+----------+--------------------------+
2 rows in set, 2 warnings (0.00 sec)

root@[test] 13:38:18>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1276
Message: Field or reference 'test.t1.a1' of SELECT #2 was resolved in SELECT #1
*************************** 2. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where exists(/* select#2 */ select 1 from `test`.`t2` where ((`test`.`t1`.`a1` = `test`.`t2`.`a2`) and (`test`.`t2`.`a2` > 10)))
2 rows in set (0.00 sec)

ERROR: 
No query specified

子查询存在,没有进行优化。

mariadb 10.0.2:
root@[test] 13:39:51>explain extended select * from t1 where exists(select 1 from t2 where t1.a1=t2.a2 and t2.a2>10);
+------+--------------+-------------+--------+---------------+--------------+---------+------+-------+----------+--------------------------+
| id   | select_type  | table       | type   | possible_keys | key          | key_len | ref  | rows  | filtered | Extra                    |
+------+--------------+-------------+--------+---------------+--------------+---------+------+-------+----------+--------------------------+
|    1 | PRIMARY      | t1          | ALL    | t_idx_t1      | NULL         | NULL    | NULL | 10157 |    50.00 |                          |
|    1 | PRIMARY      | <subquery2> | eq_ref | distinct_key  | distinct_key | 4       | func |     1 |   100.00 |                          |
|    2 | MATERIALIZED | t2          | range  | t_idx_t2      | t_idx_t2     | 5       | NULL |  5078 |   100.00 | Using where; Using index |
+------+--------------+-------------+--------+---------------+--------------+---------+------+-------+----------+--------------------------+
3 rows in set, 2 warnings (0.00 sec)

root@[test] 13:40:00>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1276
Message: Field or reference 'test.t1.a1' of SELECT #2 was resolved in SELECT #1
*************************** 2. row ***************************
  Level: Note
   Code: 1003
Message: select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t2`.`a2` > 10))
2 rows in set (0.00 sec)

ERROR: No query specified

mariadb对t2表上拉到上层与t1表进行半连接,同时进行物化优化

EXISTS子查询:非相关子查询
root@[test] 13:44:08>explain extended select * from t1 where exists(select 1 from t2 where t2.a2>10);
+----+-------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
| id | select_type | table | type  | possible_keys | key      | key_len | ref  | rows  | filtered | Extra                    |
+----+-------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
|  1 | PRIMARY     | t1    | ALL   | NULL          | NULL     | NULL    | NULL | 10157 |   100.00 | NULL                     |
|  2 | SUBQUERY    | t2    | range | t_idx_t2      | t_idx_t2 | 5       | NULL |  5078 |   100.00 | Using where; Using index |
+----+-------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
2 rows in set, 1 warning (0.00 sec)

root@[test] 13:46:09>show warnings;
+-------+------+--------------------------------------------------------------------------------------------------+
| Level | Code | Message                                                                                          |
+-------+------+--------------------------------------------------------------------------------------------------+
| Note  | 1003 | /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where 1 |
+-------+------+--------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mariadb 10.0.2:
root@[test] 13:44:05>explain extended select * from t1 where exists(select 1 from t2 where t2.a2>10);
+------+-------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
| id   | select_type | table | type  | possible_keys | key      | key_len | ref  | rows  | filtered | Extra                    |
+------+-------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
|    1 | PRIMARY     | t1    | ALL   | NULL          | NULL     | NULL    | NULL | 10157 |   100.00 |                          |
|    2 | SUBQUERY    | t2    | range | t_idx_t2      | t_idx_t2 | 5       | NULL |  5078 |   100.00 | Using where; Using index |
+------+-------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
2 rows in set, 1 warning (0.00 sec)

root@[test] 13:45:52>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where <in_optimizer>(1,exists(select 1 from `test`.`t2` where (`test`.`t2`.`a2` > 10)))
1 row in set (0.00 sec)

ERROR: No query specified

对非相关exists子查询语句,子查询还存在,内部没有做进一步优化。

总结:
mysql 5.6对exists子查询没有做进一步优化操作,而mariadb 10.0.2对exists关联子查询进行半连接优化,对exists非关联子查询没有进一步进行优化。

5、NOT EXISTS子查询:相关子查询
root@[test] 13:51:59>explain extended select * from t1 where not exists (select 1 from t2 where t1.a1=t2.a2 and t2.a2>10);
+----+--------------------+-------+------+---------------+----------+---------+------------+-------+----------+--------------------------+
| id | select_type        | table | type | possible_keys | key      | key_len | ref        | rows  | filtered | Extra                    |
+----+--------------------+-------+------+---------------+----------+---------+------------+-------+----------+--------------------------+
|  1 | PRIMARY            | t1    | ALL  | NULL          | NULL     | NULL    | NULL       | 10157 |   100.00 | Using where              |
|  2 | DEPENDENT SUBQUERY | t2    | ref  | t_idx_t2      | t_idx_t2 | 5       | test.t1.a1 |     1 |   100.00 | Using where; Using index |
+----+--------------------+-------+------+---------------+----------+---------+------------+-------+----------+--------------------------+
2 rows in set, 2 warnings (0.00 sec)

root@[test] 13:55:18>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1276
Message: Field or reference 'test.t1.a1' of SELECT #2 was resolved in SELECT #1
*************************** 2. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where (not(exists(/* select#2 */ select 1 from `test`.`t2` where ((`test`.`t1`.`a1` = `test`.`t2`.`a2`) and (`test`.`t2`.`a2` > 10)))))
2 rows in set (0.00 sec)

ERROR: 
No query specified

子查询存在,没有进一步进行优化。

mariadb 10.0.2:
root@[test] 13:51:55>explain extended select * from t1 where not exists (select 1 from t2 where t1.a1=t2.a2 and t2.a2>10);
+------+--------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
| id   | select_type  | table | type  | possible_keys | key      | key_len | ref  | rows  | filtered | Extra                    |
+------+--------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
|    1 | PRIMARY      | t1    | ALL   | NULL          | NULL     | NULL    | NULL | 10157 |   100.00 | Using where              |
|    2 | MATERIALIZED | t2    | range | t_idx_t2      | t_idx_t2 | 5       | NULL |  5078 |   100.00 | Using where; Using index |
+------+--------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
2 rows in set, 2 warnings (0.00 sec)

root@[test] 13:55:29>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1276
Message: Field or reference 'test.t1.a1' of SELECT #2 was resolved in SELECT #1
*************************** 2. row ***************************
  Level: Note
   Code: 1003
Message: select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where (not(((`test`.`t1`.`a1` is not null) and <expr_cache><`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t1`.`a1`,`test`.`t1`.`a1` in ( <materialize> (select `test`.`t2`.`a2` from `test`.`t2` where ((`test`.`t2`.`a2` is not null) and (`test`.`t2`.`a2` > 10)) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `<subquery2>`.`a2`)))))))))
2 rows in set (0.00 sec)

ERROR: No query specified

mariadb进行物化优化。

NOT EXISTS子查询:非相关子查询
root@[test] 13:59:43>explain extended select * from t1 where not exists (select 1 from t2 where t2.a2>10);
+----+-------------+-------+-------+---------------+----------+---------+------+------+----------+--------------------------+
| id | select_type | table | type  | possible_keys | key      | key_len | ref  | rows | filtered | Extra                    |
+----+-------------+-------+-------+---------------+----------+---------+------+------+----------+--------------------------+
|  1 | PRIMARY     | NULL  | NULL  | NULL          | NULL     | NULL    | NULL | NULL |     NULL | Impossible WHERE         |
|  2 | SUBQUERY    | t2    | range | t_idx_t2      | t_idx_t2 | 5       | NULL | 5078 |   100.00 | Using where; Using index |
+----+-------------+-------+-------+---------------+----------+---------+------+------+----------+--------------------------+
2 rows in set, 1 warning (0.00 sec)

root@[test] 13:59:46>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where 0
1 row in set (0.00 sec)

ERROR: 
No query specified

mariadb 10.0.2:
root@[test] 13:55:36>explain extended select * from t1 where not exists (select 1 from t2 where t2.a2>10);
+------+-------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
| id   | select_type | table | type  | possible_keys | key      | key_len | ref  | rows  | filtered | Extra                    |
+------+-------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
|    1 | PRIMARY     | t1    | ALL   | NULL          | NULL     | NULL    | NULL | 10157 |   100.00 |                          |
|    2 | SUBQUERY    | t2    | range | t_idx_t2      | t_idx_t2 | 5       | NULL |  5078 |   100.00 | Using where; Using index |
+------+-------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
2 rows in set, 1 warning (0.00 sec)

root@[test] 13:59:59>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where (not(<in_optimizer>(1,exists(select 1 from `test`.`t2` where (`test`.`t2`.`a2` > 10)))))
1 row in set (0.00 sec)

ERROR: No query specified

子查询存在,没有进一步进行优化。

总结:
对not exists子查询,mysql和mariadb都没有进一步优化。

6、IN子查询:非相关子查询
root@[test] 14:03:03>explain extended select * from t1 where t1.a1 in (select a2 from t2 where t2.a2>10);
+----+--------------+-------------+--------+---------------+------------+---------+------------+-------+----------+--------------------------+
| id | select_type  | table       | type   | possible_keys | key        | key_len | ref        | rows  | filtered | Extra                    |
+----+--------------+-------------+--------+---------------+------------+---------+------------+-------+----------+--------------------------+
|  1 | SIMPLE       | t1          | ALL    | t_idx_t1      | NULL       | NULL    | NULL       | 10157 |    50.00 | Using where              |
|  1 | SIMPLE       | <subquery2> | eq_ref | <auto_key>    | <auto_key> | 5       | test.t1.a1 |     1 |   100.00 | NULL                     |
|  2 | MATERIALIZED | t2          | range  | t_idx_t2      | t_idx_t2   | 5       | NULL       |  5078 |   100.00 | Using where; Using index |
+----+--------------+-------------+--------+---------------+------------+---------+------------+-------+----------+--------------------------+
3 rows in set, 1 warning (0.00 sec)

root@[test] 14:05:49>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` semi join (`test`.`t2`) where ((`<subquery2>`.`a2` = `test`.`t1`.`a1`) and (`test`.`t2`.`a2` > 10))
1 row in set (0.00 sec)

ERROR: 
No query specified

mariadb 10.0.2:
root@[test] 14:03:13>explain extended select * from t1 where t1.a1 in (select a2 from t2 where t2.a2>10);
+------+--------------+-------------+--------+---------------+--------------+---------+------+-------+----------+--------------------------+
| id   | select_type  | table       | type   | possible_keys | key          | key_len | ref  | rows  | filtered | Extra                    |
+------+--------------+-------------+--------+---------------+--------------+---------+------+-------+----------+--------------------------+
|    1 | PRIMARY      | t1          | ALL    | t_idx_t1      | NULL         | NULL    | NULL | 10157 |    50.00 |                          |
|    1 | PRIMARY      | <subquery2> | eq_ref | distinct_key  | distinct_key | 4       | func |     1 |   100.00 |                          |
|    2 | MATERIALIZED | t2          | range  | t_idx_t2      | t_idx_t2     | 5       | NULL |  5078 |   100.00 | Using where; Using index |
+------+--------------+-------------+--------+---------------+--------------+---------+------+-------+----------+--------------------------+
3 rows in set, 1 warning (0.00 sec)

root@[test] 14:06:01>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t2`.`a2` > 10))
1 row in set (0.00 sec)

ERROR: No query specified

将t2表物化后,与t1表进行半连接。

非关联子查询,子查询返回标量:
root@[test] 14:20:33>explain extended select * from t1 where t1.a1 in (select a2 from t2 where t2.a2=10);
+----+-------------+-------+------+---------------+----------+---------+-------+------+----------+-----------------------------+
| id | select_type | table | type | possible_keys | key      | key_len | ref   | rows | filtered | Extra                       |
+----+-------------+-------+------+---------------+----------+---------+-------+------+----------+-----------------------------+
|  1 | SIMPLE      | t1    | ref  | t_idx_t1      | t_idx_t1 | 5       | const |    1 |   100.00 | NULL                        |
|  1 | SIMPLE      | t2    | ref  | t_idx_t2      | t_idx_t2 | 5       | const |    1 |   100.00 | Using index; FirstMatch(t1) |
+----+-------------+-------+------+---------------+----------+---------+-------+------+----------+-----------------------------+
2 rows in set, 1 warning (0.00 sec)

root@[test] 14:21:07>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t1`.`a1` = 10) and (`test`.`t2`.`a2` = 10))
1 row in set (0.00 sec)

ERROR: 
No query specified

mariadb 10.0.2:
root@[test] 14:06:03>explain extended select * from t1 where t1.a1 in (select a2 from t2 where t2.a2=10);
+------+-------------+-------+------+---------------+----------+---------+-------+------+----------+------------------------+
| id   | select_type | table | type | possible_keys | key      | key_len | ref   | rows | filtered | Extra                  |
+------+-------------+-------+------+---------------+----------+---------+-------+------+----------+------------------------+
|    1 | PRIMARY     | t2    | ref  | t_idx_t2      | t_idx_t2 | 5       | const |    1 |   100.00 | Using index; LooseScan |
|    1 | PRIMARY     | t1    | ref  | t_idx_t1      | t_idx_t1 | 5       | const |    1 |   100.00 |                        |
+------+-------------+-------+------+---------------+----------+---------+-------+------+----------+------------------------+
2 rows in set, 1 warning (0.00 sec)

root@[test] 14:08:19>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t2`.`a2` = 10) and (`test`.`t1`.`a1` = 10))
1 row in set (0.00 sec)

ERROR: No query specified

子查询不存在,都使用半连接优化,但是在基于代价评估时选择了不同的策略,mysql选择FirstMatch,mariadb选择LooseScan;

IN子查询:相关子查询
root@[test] 14:21:09>explain extended select * from t1 where t1.a1 in (select a2 from t2 where t1.a1=10);
+----+-------------+-------+------+---------------+----------+---------+-------+------+----------+-----------------------------+
| id | select_type | table | type | possible_keys | key      | key_len | ref   | rows | filtered | Extra                       |
+----+-------------+-------+------+---------------+----------+---------+-------+------+----------+-----------------------------+
|  1 | SIMPLE      | t1    | ref  | t_idx_t1      | t_idx_t1 | 5       | const |    1 |   100.00 | NULL                        |
|  1 | SIMPLE      | t2    | ref  | t_idx_t2      | t_idx_t2 | 5       | const |    1 |   100.00 | Using index; FirstMatch(t1) |
+----+-------------+-------+------+---------------+----------+---------+-------+------+----------+-----------------------------+
2 rows in set, 2 warnings (0.00 sec)

root@[test] 14:34:54>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1276
Message: Field or reference 'test.t1.a1' of SELECT #2 was resolved in SELECT #1
*************************** 2. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t1`.`a1` = 10) and (`test`.`t2`.`a2` = 10))
2 rows in set (0.00 sec)

ERROR: 
No query specified

mariadb 10.0.2:
root@[test] 14:20:21>explain extended select * from t1 where t1.a1 in (select a2 from t2 where t1.a1=10);
+------+-------------+-------+------+---------------+----------+---------+-------+------+----------+-----------------------------+
| id   | select_type | table | type | possible_keys | key      | key_len | ref   | rows | filtered | Extra                       |
+------+-------------+-------+------+---------------+----------+---------+-------+------+----------+-----------------------------+
|    1 | PRIMARY     | t1    | ref  | t_idx_t1      | t_idx_t1 | 5       | const |    1 |   100.00 |                             |
|    1 | PRIMARY     | t2    | ref  | t_idx_t2      | t_idx_t2 | 5       | const |    1 |   100.00 | Using index; FirstMatch(t1) |
+------+-------------+-------+------+---------------+----------+---------+-------+------+----------+-----------------------------+
2 rows in set, 2 warnings (0.00 sec)

root@[test] 14:34:36>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1276
Message: Field or reference 'test.t1.a1' of SELECT #2 was resolved in SELECT #1
*************************** 2. row ***************************
  Level: Note
   Code: 1003
Message: select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t1`.`a1` = 10) and (`test`.`t2`.`a2` = 10))
2 rows in set (0.00 sec)

ERROR: No query specified

子查询不存在,使用半连接进行优化

总结:
mysql和mariadb对in子查询,对满足半连接语义的查询进行半连接优化,然后对满足某些条件的,再基于代价评估进行优化。

7、NOT IN子查询:非关联子查询
root@[test] 14:39:25>explain extended select * from t1 where t1.a1 not in (select a2 from t2 where t2.a2>10);
+----+-------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
| id | select_type | table | type  | possible_keys | key      | key_len | ref  | rows  | filtered | Extra                    |
+----+-------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
|  1 | PRIMARY     | t1    | ALL   | NULL          | NULL     | NULL    | NULL | 10157 |   100.00 | Using where              |
|  2 | SUBQUERY    | t2    | range | t_idx_t2      | t_idx_t2 | 5       | NULL |  5078 |   100.00 | Using where; Using index |
+----+-------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
2 rows in set, 1 warning (0.00 sec)

root@[test] 14:39:51>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where (not(<in_optimizer>(`test`.`t1`.`a1`,`test`.`t1`.`a1` in ( <materialize> (/* select#2 */ select `test`.`t2`.`a2` from `test`.`t2` where (`test`.`t2`.`a2` > 10) having 1 ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on <auto_key> where ((`test`.`t1`.`a1` = `materialized-subquery`.`a2`)))))))
1 row in set (0.00 sec)

ERROR: 
No query specified

mariadb 10.0.2:
root@[test] 14:35:38>explain extended select * from t1 where t1.a1 not in (select a2 from t2 where t2.a2>10);
+------+--------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
| id   | select_type  | table | type  | possible_keys | key      | key_len | ref  | rows  | filtered | Extra                    |
+------+--------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
|    1 | PRIMARY      | t1    | ALL   | NULL          | NULL     | NULL    | NULL | 10157 |   100.00 | Using where              |
|    2 | MATERIALIZED | t2    | range | t_idx_t2      | t_idx_t2 | 5       | NULL |  5078 |   100.00 | Using where; Using index |
+------+--------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
2 rows in set, 1 warning (0.00 sec)

root@[test] 14:40:11>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where (not(<expr_cache><`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t1`.`a1`,`test`.`t1`.`a1` in ( <materialize> (select `test`.`t2`.`a2` from `test`.`t2` where (`test`.`t2`.`a2` > 10) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `<subquery2>`.`a2`))))))))
1 row in set (0.00 sec)

ERROR: No query specified

对子查询进行物化优化,子查询存在。

NOT IN子查询:关联子查询
root@[test] 14:44:08>explain extended select * from t1 where t1.a1 not in (select a2 from t2 where t1.a1=10);----+--------------------+-------+----------------+---------------+----------+---------+------+-------+----------+------------------------------------
| id | select_type        | table | type           | possible_keys | key      | key_len | ref  | rows  | filtered | Extra|----+--------------------+-------+----------------+---------------+----------+---------+------+-------+----------+------------------------------------
|  1 | PRIMARY            | t1    | ALL            | NULL          | NULL     | NULL    | NULL | 10157 |   100.00 | Using where|
|  2 | DEPENDENT SUBQUERY | t2    | index_subquery | t_idx_t2      | t_idx_t2 | 5       | func |     2 |   100.00 | Using index; Using where; Full scan on NULL key |----+--------------------+-------+----------------+---------------+----------+---------+------+-------+----------+------------------------------------
2 rows in set, 2 warnings (0.00 sec)

root@[test] 14:44:48>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1276
Message: Field or reference 'test.t1.a1' of SELECT #2 was resolved in SELECT #1
*************************** 2. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where (not(<in_optimizer>(`test`.`t1`.`a1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`a1`) in t2 on t_idx_t2 checking NULL where (`test`.`t1`.`a1` = 10) having <if>(outer_field_is_not_null, <is_not_null_test>(`test`.`t2`.`a2`), true))))))
2 rows in set (0.00 sec)

ERROR: 
No query specified

mariadb 10.0.2:
root@[test] 14:44:15>explain extended select * from t1 where t1.a1 not in (select a2 from t2 where t1.a1=10);
------+--------------------+-------+----------------+---------------+----------+---------+------+-------+----------+----------------------------------
| id   | select_type        | table | type           | possible_keys | key      | key_len | ref  | rows  | filtered | Extra|
------+--------------------+-------+----------------+---------------+----------+---------+------+-------+----------+----------------------------------
|    1 | PRIMARY            | t1    | ALL            | NULL          | NULL     | NULL    | NULL | 10157 |   100.00 | Using where|
|    2 | DEPENDENT SUBQUERY | t2    | index_subquery | t_idx_t2      | t_idx_t2 | 5       | func |     2 |   100.00 | Using index; Using where; Full scan on NULL key |
------+--------------------+-------+----------------+---------------+----------+---------+------+-------+----------+----------------------------------
2 rows in set, 2 warnings (0.00 sec)

root@[test] 14:44:33>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1276
Message: Field or reference 'test.t1.a1' of SELECT #2 was resolved in SELECT #1
*************************** 2. row ***************************
  Level: Note
   Code: 1003
Message: select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where (not(<expr_cache><`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t1`.`a1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`a1`) in t2 on t_idx_t2 checking NULL where (`test`.`t1`.`a1` = 10) having trigcond(<is_not_null_test>(`test`.`t2`.`a2`))))))))
2 rows in set (0.00 sec)

ERROR: No query specified

对not in子查询,子查询存在,没有做优化。

8、ALL子查询
>ALL:不相关子查询
root@[test] 14:44:50>explain extended select * from t1 where t1.a1 > all (select a2 from t2 where t2.a2>10);
+----+-------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
| id | select_type | table | type  | possible_keys | key      | key_len | ref  | rows  | filtered | Extra                    |
+----+-------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
|  1 | PRIMARY     | t1    | ALL   | NULL          | NULL     | NULL    | NULL | 10157 |   100.00 | Using where              |
|  2 | SUBQUERY    | t2    | range | t_idx_t2      | t_idx_t2 | 5       | NULL |  5078 |   100.00 | Using where; Using index |
+----+-------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
2 rows in set, 1 warning (0.00 sec)

root@[test] 14:49:47>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where <not>((`test`.`t1`.`a1` <= <max>(/* select#2 */ select `test`.`t2`.`a2` from `test`.`t2` where (`test`.`t2`.`a2` > 10))))
1 row in set (0.00 sec)

ERROR: 
No query specified

mariadb 10.0.2:
root@[test] 14:44:35>explain extended select * from t1 where t1.a1 > all (select a2 from t2 where t2.a2>10);
+------+-------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
| id   | select_type | table | type  | possible_keys | key      | key_len | ref  | rows  | filtered | Extra                    |
+------+-------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
|    1 | PRIMARY     | t1    | ALL   | NULL          | NULL     | NULL    | NULL | 10157 |   100.00 | Using where              |
|    2 | SUBQUERY    | t2    | range | t_idx_t2      | t_idx_t2 | 5       | NULL |  5078 |   100.00 | Using where; Using index |
+------+-------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
2 rows in set, 1 warning (0.00 sec)

root@[test] 14:50:05>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where <not>(<in_optimizer>(`test`.`t1`.`a1`,(<max>(select `test`.`t2`.`a2` from `test`.`t2` where (`test`.`t2`.`a2` > 10)) >= <cache>(`test`.`t1`.`a1`))))
1 row in set (0.00 sec)

ERROR: No query specified

子查询使用max函数限制,利用索引有最大值

>ALL:相关子查询
root@[test] 14:49:56>explain extended select * from t1 where t1.a1 > all (select a2 from t2 where t1.a1>10);
+----+--------------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
| id | select_type        | table | type  | possible_keys | key      | key_len | ref  | rows  | filtered | Extra                    |
+----+--------------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
|  1 | PRIMARY            | t1    | ALL   | NULL          | NULL     | NULL    | NULL | 10157 |   100.00 | Using where              |
|  2 | DEPENDENT SUBQUERY | t2    | index | NULL          | t_idx_t2 | 5       | NULL | 10157 |   100.00 | Using where; Using index |
+----+--------------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
2 rows in set, 2 warnings (0.00 sec)

root@[test] 14:52:48>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1276
Message: Field or reference 'test.t1.a1' of SELECT #2 was resolved in SELECT #1
*************************** 2. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where <not>(<in_optimizer>(`test`.`t1`.`a1`,<exists>(/* select#2 */ select 1 from `test`.`t2` where ((`test`.`t1`.`a1` > 10) and <if>(outer_field_is_not_null, ((<cache>(`test`.`t1`.`a1`) <= `test`.`t2`.`a2`) or isnull(`test`.`t2`.`a2`)), true)) having <if>(outer_field_is_not_null, <is_not_null_test>(`test`.`t2`.`a2`), true))))
2 rows in set (0.00 sec)

ERROR: 
No query specified

mariadb 10.0.2:
root@[test] 14:50:08>explain extended select * from t1 where t1.a1 > all (select a2 from t2 where t1.a1>10);
+------+--------------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
| id   | select_type        | table | type  | possible_keys | key      | key_len | ref  | rows  | filtered | Extra                    |
+------+--------------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
|    1 | PRIMARY            | t1    | ALL   | NULL          | NULL     | NULL    | NULL | 10157 |   100.00 | Using where              |
|    2 | DEPENDENT SUBQUERY | t2    | index | NULL          | t_idx_t2 | 5       | NULL | 10157 |   100.00 | Using where; Using index |
+------+--------------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
2 rows in set, 2 warnings (0.00 sec)

root@[test] 14:52:35>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1276
Message: Field or reference 'test.t1.a1' of SELECT #2 was resolved in SELECT #1
*************************** 2. row ***************************
  Level: Note
   Code: 1003
Message: select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where <not>(<expr_cache><`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t1`.`a1`,<exists>(select `test`.`t2`.`a2` from `test`.`t2` where ((`test`.`t1`.`a1` > 10) and trigcond(((<cache>(`test`.`t1`.`a1`) <= `test`.`t2`.`a2`) or isnull(`test`.`t2`.`a2`)))) having trigcond(<is_not_null_test>(`test`.`t2`.`a2`))))))
2 rows in set (0.00 sec)

ERROR: No query specified

对关联>all子查询,子查询存在,使用exists 方式优化。

=ALL:非相关子查询
root@[test] 14:56:16>explain extended select * from t1 where t1.a1=all(select a2 from t2 where t2.a2=10);
+----+--------------------+-------+------+---------------+----------+---------+-------+-------+----------+--------------------------+
| id | select_type        | table | type | possible_keys | key      | key_len | ref   | rows  | filtered | Extra                    |
+----+--------------------+-------+------+---------------+----------+---------+-------+-------+----------+--------------------------+
|  1 | PRIMARY            | t1    | ALL  | NULL          | NULL     | NULL    | NULL  | 10157 |   100.00 | Using where              |
|  2 | DEPENDENT SUBQUERY | t2    | ref  | t_idx_t2      | t_idx_t2 | 5       | const |     1 |   100.00 | Using where; Using index |
+----+--------------------+-------+------+---------------+----------+---------+-------+-------+----------+--------------------------+
2 rows in set, 1 warning (0.00 sec)

root@[test] 14:56:20>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where <not>(<in_optimizer>(`test`.`t1`.`a1`,<exists>(/* select#2 */ select 1 from `test`.`t2` where ((`test`.`t2`.`a2` = 10) and <if>(outer_field_is_not_null, ((<cache>(`test`.`t1`.`a1`) <> 10) or <cache>(isnull(10))), true)) having <if>(outer_field_is_not_null, <is_not_null_test>(`test`.`t2`.`a2`), true))))
1 row in set (0.00 sec)

ERROR: 
No query specified

mariadb 10.0.2:
root@[test] 14:52:37>explain extended select * from t1 where t1.a1=all(select a2 from t2 where t2.a2=10);
+------+--------------------+-------+------+---------------+----------+---------+-------+-------+----------+--------------------------+
| id   | select_type        | table | type | possible_keys | key      | key_len | ref   | rows  | filtered | Extra                    |
+------+--------------------+-------+------+---------------+----------+---------+-------+-------+----------+--------------------------+
|    1 | PRIMARY            | t1    | ALL  | NULL          | NULL     | NULL    | NULL  | 10157 |   100.00 | Using where              |
|    2 | DEPENDENT SUBQUERY | t2    | ref  | t_idx_t2      | t_idx_t2 | 5       | const |     1 |   100.00 | Using where; Using index |
+------+--------------------+-------+------+---------------+----------+---------+-------+-------+----------+--------------------------+
2 rows in set, 1 warning (0.00 sec)

root@[test] 14:56:29>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where <not>(<expr_cache><`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t1`.`a1`,<exists>(select `test`.`t2`.`a2` from `test`.`t2` where ((`test`.`t2`.`a2` = 10) and trigcond(((<cache>(`test`.`t1`.`a1`) <> `test`.`t2`.`a2`) or isnull(`test`.`t2`.`a2`)))) having trigcond(<is_not_null_test>(`test`.`t2`.`a2`))))))
1 row in set (0.00 sec)

ERROR: No query specified

子查询存在,使用exists进行优化

<ALL:不相关子查询
root@[test] 15:00:30>explain extended select * from t1 where t1.a1 < all(select a2 from t2 where t2.a2=10);
+----+-------------+-------+------+---------------+----------+---------+-------+-------+----------+-------------+
| id | select_type | table | type | possible_keys | key      | key_len | ref   | rows  | filtered | Extra       |
+----+-------------+-------+------+---------------+----------+---------+-------+-------+----------+-------------+
|  1 | PRIMARY     | t1    | ALL  | NULL          | NULL     | NULL    | NULL  | 10157 |   100.00 | Using where |
|  2 | SUBQUERY    | t2    | ref  | t_idx_t2      | t_idx_t2 | 5       | const |     1 |   100.00 | Using index |
+----+-------------+-------+------+---------------+----------+---------+-------+-------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)

root@[test] 15:01:29>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where <not>((`test`.`t1`.`a1` >= <min>(/* select#2 */ select `test`.`t2`.`a2` from `test`.`t2` where (`test`.`t2`.`a2` = 10))))
1 row in set (0.00 sec)

ERROR: 
No query specified

mariadb 10.0.2:
root@[test] 15:00:17>explain extended select * from t1 where t1.a1 < all(select a2 from t2 where t2.a2=10);
+------+-------------+-------+------+---------------+----------+---------+-------+-------+----------+-------------+
| id   | select_type | table | type | possible_keys | key      | key_len | ref   | rows  | filtered | Extra       |
+------+-------------+-------+------+---------------+----------+---------+-------+-------+----------+-------------+
|    1 | PRIMARY     | t1    | ALL  | NULL          | NULL     | NULL    | NULL  | 10157 |   100.00 | Using where |
|    2 | SUBQUERY    | t2    | ref  | t_idx_t2      | t_idx_t2 | 5       | const |     1 |   100.00 | Using index |
+------+-------------+-------+------+---------------+----------+---------+-------+-------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)

root@[test] 15:01:37>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where <not>(<in_optimizer>(`test`.`t1`.`a1`,(<min>(select `test`.`t2`.`a2` from `test`.`t2` where (`test`.`t2`.`a2` = 10)) <= <cache>(`test`.`t1`.`a1`))))
1 row in set (0.00 sec)

ERROR: No query specified

子查询使用min函数限制,利用索引求最小值。

总结:
mysql和mariadb对>all非关联子查询使用max函数,<all非关联子查询使用min函数,对=all和非关联子查询使用exists优化。

9、some和any子查询:
>some和>any非关联子查询
root@[test] 15:03:10>explain extended select * from t1 where t1.a1 > some(select a2 from t2 where t2.a2 >10);
+----+-------------+-------+------+---------------+------+---------+------+-------+----------+------------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra                        |
+----+-------------+-------+------+---------------+------+---------+------+-------+----------+------------------------------+
|  1 | PRIMARY     | t1    | ALL  | NULL          | NULL | NULL    | NULL | 10157 |   100.00 | Using where                  |
|  2 | SUBQUERY    | NULL  | NULL | NULL          | NULL | NULL    | NULL |  NULL |     NULL | Select tables optimized away |
+----+-------------+-------+------+---------------+------+---------+------+-------+----------+------------------------------+
2 rows in set, 1 warning (0.00 sec)

root@[test] 15:10:51>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where <nop>((`test`.`t1`.`a1` > (/* select#2 */ select min(`test`.`t2`.`a2`) from `test`.`t2` where (`test`.`t2`.`a2` > 10))))
1 row in set (0.00 sec)

ERROR: 
No query specified

root@[test] 15:10:53>explain extended select * from t1 where t1.a1 > any(select a2 from t2 where t2.a2 >10);
+----+-------------+-------+------+---------------+------+---------+------+-------+----------+------------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra                        |
+----+-------------+-------+------+---------------+------+---------+------+-------+----------+------------------------------+
|  1 | PRIMARY     | t1    | ALL  | NULL          | NULL | NULL    | NULL | 10157 |   100.00 | Using where                  |
|  2 | SUBQUERY    | NULL  | NULL | NULL          | NULL | NULL    | NULL |  NULL |     NULL | Select tables optimized away |
+----+-------------+-------+------+---------------+------+---------+------+-------+----------+------------------------------+
2 rows in set, 1 warning (0.00 sec)

root@[test] 15:11:47>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where <nop>((`test`.`t1`.`a1` > (/* select#2 */ select min(`test`.`t2`.`a2`) from `test`.`t2` where (`test`.`t2`.`a2` > 10))))
1 row in set (0.00 sec)

ERROR: 
No query specified

mariadb 10.0.2:
root@[test] 15:10:10>explain extended select * from t1 where t1.a1 > some(select a2 from t2 where t2.a2 >10);
+------+-------------+-------+------+---------------+------+---------+------+-------+----------+------------------------------+
| id   | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra                        |
+------+-------------+-------+------+---------------+------+---------+------+-------+----------+------------------------------+
|    1 | PRIMARY     | t1    | ALL  | NULL          | NULL | NULL    | NULL | 10157 |   100.00 | Using where                  |
|    2 | SUBQUERY    | NULL  | NULL | NULL          | NULL | NULL    | NULL |  NULL |     NULL | Select tables optimized away |
+------+-------------+-------+------+---------------+------+---------+------+-------+----------+------------------------------+
2 rows in set, 1 warning (0.00 sec)

root@[test] 15:10:21>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where <nop>(<in_optimizer>(`test`.`t1`.`a1`,((select min(`test`.`t2`.`a2`) from `test`.`t2` where (`test`.`t2`.`a2` > 10)) < <cache>(`test`.`t1`.`a1`))))
1 row in set (0.00 sec)

ERROR: No query specified

子查询存在,但是使用min进行限制,利用索引求最小值。

>some和>any关联子查询
root@[test] 15:14:19>explain extended select * from t1 where t1.a1 > any(select a2 from t2 where t1.a1 >10);
+----+--------------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
| id | select_type        | table | type  | possible_keys | key      | key_len | ref  | rows  | filtered | Extra                    |
+----+--------------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
|  1 | PRIMARY            | t1    | ALL   | NULL          | NULL     | NULL    | NULL | 10157 |   100.00 | Using where              |
|  2 | DEPENDENT SUBQUERY | t2    | index | NULL          | t_idx_t2 | 5       | NULL | 10157 |   100.00 | Using where; Using index |
+----+--------------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
2 rows in set, 2 warnings (0.00 sec)

root@[test] 15:15:01>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1276
Message: Field or reference 'test.t1.a1' of SELECT #2 was resolved in SELECT #1
*************************** 2. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where <nop>(<in_optimizer>(`test`.`t1`.`a1`,<exists>(/* select#2 */ select 1 from `test`.`t2` where ((`test`.`t1`.`a1` > 10) and <if>(outer_field_is_not_null, ((<cache>(`test`.`t1`.`a1`) > `test`.`t2`.`a2`) or isnull(`test`.`t2`.`a2`)), true)) having <if>(outer_field_is_not_null, <is_not_null_test>(`test`.`t2`.`a2`), true))))
2 rows in set (0.00 sec)

ERROR: 
No query specified

mariadb 10.0.2:
root@[test] 15:10:22>explain extended select * from t1 where t1.a1 > any(select a2 from t2 where t1.a1 >10);
+------+--------------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
| id   | select_type        | table | type  | possible_keys | key      | key_len | ref  | rows  | filtered | Extra                    |
+------+--------------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
|    1 | PRIMARY            | t1    | ALL   | NULL          | NULL     | NULL    | NULL | 10157 |   100.00 | Using where              |
|    2 | DEPENDENT SUBQUERY | t2    | index | NULL          | t_idx_t2 | 5       | NULL | 10157 |   100.00 | Using where; Using index |
+------+--------------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
2 rows in set, 2 warnings (0.00 sec)

root@[test] 15:15:13>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1276
Message: Field or reference 'test.t1.a1' of SELECT #2 was resolved in SELECT #1
*************************** 2. row ***************************
  Level: Note
   Code: 1003
Message: select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where <nop>(<expr_cache><`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t1`.`a1`,<exists>(select `test`.`t2`.`a2` from `test`.`t2` where ((`test`.`t1`.`a1` > 10) and trigcond(((<cache>(`test`.`t1`.`a1`) > `test`.`t2`.`a2`) or isnull(`test`.`t2`.`a2`)))) having trigcond(<is_not_null_test>(`test`.`t2`.`a2`))))))
2 rows in set (0.00 sec)

ERROR: No query specified

对关联子查询,子查询存在,使用了exists优化。

=some和=any非关联子查询
root@[test] 15:17:21>explain extended select * from t1 where t1.a1 = any(select a2 from t2 where t2.a2 =10);
+----+-------------+-------+------+---------------+----------+---------+-------+------+----------+-----------------------------+
| id | select_type | table | type | possible_keys | key      | key_len | ref   | rows | filtered | Extra                       |
+----+-------------+-------+------+---------------+----------+---------+-------+------+----------+-----------------------------+
|  1 | SIMPLE      | t1    | ref  | t_idx_t1      | t_idx_t1 | 5       | const |    1 |   100.00 | NULL                        |
|  1 | SIMPLE      | t2    | ref  | t_idx_t2      | t_idx_t2 | 5       | const |    1 |   100.00 | Using index; FirstMatch(t1) |
+----+-------------+-------+------+---------------+----------+---------+-------+------+----------+-----------------------------+
2 rows in set, 1 warning (0.00 sec)

root@[test] 15:17:35>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t1`.`a1` = 10) and (`test`.`t2`.`a2` = 10))
1 row in set (0.00 sec)

ERROR: 
No query specified

mariadb 10.0.2:
root@[test] 15:17:01>explain extended select * from t1 where t1.a1 = any(select a2 from t2 where t2.a2 =10);
+------+-------------+-------+------+---------------+----------+---------+-------+------+----------+------------------------+
| id   | select_type | table | type | possible_keys | key      | key_len | ref   | rows | filtered | Extra                  |
+------+-------------+-------+------+---------------+----------+---------+-------+------+----------+------------------------+
|    1 | PRIMARY     | t2    | ref  | t_idx_t2      | t_idx_t2 | 5       | const |    1 |   100.00 | Using index; LooseScan |
|    1 | PRIMARY     | t1    | ref  | t_idx_t1      | t_idx_t1 | 5       | const |    1 |   100.00 |                        |
+------+-------------+-------+------+---------------+----------+---------+-------+------+----------+------------------------+
2 rows in set, 1 warning (0.00 sec)

root@[test] 15:17:42>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t2`.`a2` = 10) and (`test`.`t1`.`a1` = 10))
1 row in set (0.00 sec)

ERROR: No query specified

子查询不存在,使用半连接进行优化,但是mysql和mariadb在进行代价评估时使用了不同的优化方法。

=some和=any关联子查询
root@[test] 15:17:36>explain extended select * from t1 where t1.a1 = any(select a2 from t2 where t1.a1 =10);
+----+-------------+-------+------+---------------+----------+---------+-------+------+----------+-----------------------------+
| id | select_type | table | type | possible_keys | key      | key_len | ref   | rows | filtered | Extra                       |
+----+-------------+-------+------+---------------+----------+---------+-------+------+----------+-----------------------------+
|  1 | SIMPLE      | t1    | ref  | t_idx_t1      | t_idx_t1 | 5       | const |    1 |   100.00 | NULL                        |
|  1 | SIMPLE      | t2    | ref  | t_idx_t2      | t_idx_t2 | 5       | const |    1 |   100.00 | Using index; FirstMatch(t1) |
+----+-------------+-------+------+---------------+----------+---------+-------+------+----------+-----------------------------+
2 rows in set, 2 warnings (0.00 sec)

root@[test] 15:20:22>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1276
Message: Field or reference 'test.t1.a1' of SELECT #2 was resolved in SELECT #1
*************************** 2. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t1`.`a1` = 10) and (`test`.`t2`.`a2` = 10))
2 rows in set (0.00 sec)

ERROR: 
No query specified

mariadb 10.0.2:
root@[test] 15:17:43>explain extended select * from t1 where t1.a1 = any(select a2 from t2 where t1.a1 =10);
+------+-------------+-------+------+---------------+----------+---------+-------+------+----------+-----------------------------+
| id   | select_type | table | type | possible_keys | key      | key_len | ref   | rows | filtered | Extra                       |
+------+-------------+-------+------+---------------+----------+---------+-------+------+----------+-----------------------------+
|    1 | PRIMARY     | t1    | ref  | t_idx_t1      | t_idx_t1 | 5       | const |    1 |   100.00 |                             |
|    1 | PRIMARY     | t2    | ref  | t_idx_t2      | t_idx_t2 | 5       | const |    1 |   100.00 | Using index; FirstMatch(t1) |
+------+-------------+-------+------+---------------+----------+---------+-------+------+----------+-----------------------------+
2 rows in set, 2 warnings (0.00 sec)

root@[test] 15:20:06>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1276
Message: Field or reference 'test.t1.a1' of SELECT #2 was resolved in SELECT #1
*************************** 2. row ***************************
  Level: Note
   Code: 1003
Message: select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t1`.`a1` = 10) and (`test`.`t2`.`a2` = 10))
2 rows in set (0.00 sec)

ERROR: No query specified

子查询不存在,使用半连接进行优化。

<some和<any非关联子查询:
root@[test] 15:21:57>explain extended select * from t1 where t1.a1<some(select a2 from t2 where t2.a2=10);
+----+-------------+-------+------+---------------+------+---------+------+-------+----------+------------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra                        |
+----+-------------+-------+------+---------------+------+---------+------+-------+----------+------------------------------+
|  1 | PRIMARY     | t1    | ALL  | NULL          | NULL | NULL    | NULL | 10157 |   100.00 | Using where                  |
|  2 | SUBQUERY    | NULL  | NULL | NULL          | NULL | NULL    | NULL |  NULL |     NULL | Select tables optimized away |
+----+-------------+-------+------+---------------+------+---------+------+-------+----------+------------------------------+
2 rows in set, 1 warning (0.00 sec)

root@[test] 15:24:09>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where <nop>((`test`.`t1`.`a1` < (/* select#2 */ select max(`test`.`t2`.`a2`) from `test`.`t2` where multiple equal(10, `test`.`t2`.`a2`))))
1 row in set (0.00 sec)

ERROR: 
No query specified

root@[test] 15:24:11>explain extended select * from t1 where t1.a1<any(select a2 from t2 where t2.a2=10);
+----+-------------+-------+------+---------------+------+---------+------+-------+----------+------------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra                        |
+----+-------------+-------+------+---------------+------+---------+------+-------+----------+------------------------------+
|  1 | PRIMARY     | t1    | ALL  | NULL          | NULL | NULL    | NULL | 10157 |   100.00 | Using where                  |
|  2 | SUBQUERY    | NULL  | NULL | NULL          | NULL | NULL    | NULL |  NULL |     NULL | Select tables optimized away |
+----+-------------+-------+------+---------------+------+---------+------+-------+----------+------------------------------+
2 rows in set, 1 warning (0.00 sec)

root@[test] 15:25:56>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where <nop>((`test`.`t1`.`a1` < (/* select#2 */ select max(`test`.`t2`.`a2`) from `test`.`t2` where multiple equal(10, `test`.`t2`.`a2`))))
1 row in set (0.00 sec)

ERROR: 

mariadb 10.0.2:
root@[test] 15:21:53>explain extended select * from t1 where t1.a1<some(select a2 from t2 where t2.a2=10);
+------+-------------+-------+------+---------------+------+---------+------+-------+----------+------------------------------+
| id   | select_type | table | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra                        |
+------+-------------+-------+------+---------------+------+---------+------+-------+----------+------------------------------+
|    1 | PRIMARY     | t1    | ALL  | NULL          | NULL | NULL    | NULL | 10157 |   100.00 | Using where                  |
|    2 | SUBQUERY    | NULL  | NULL | NULL          | NULL | NULL    | NULL |  NULL |     NULL | Select tables optimized away |
+------+-------------+-------+------+---------------+------+---------+------+-------+----------+------------------------------+
2 rows in set, 1 warning (0.00 sec)

root@[test] 15:24:19>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where <nop>(<in_optimizer>(`test`.`t1`.`a1`,((select max(`test`.`t2`.`a2`) from `test`.`t2` where multiple equal(10, `test`.`t2`.`a2`)) > <cache>(`test`.`t1`.`a1`))))
1 row in set (0.00 sec)

ERROR: No query specified

子查询存在,但是还有max函数限制,利用索引求最大值。

<some和<any关联子查询:
root@[test] 15:26:05>explain extended select * from t1 where t1.a1<any(select a2 from t2 where t1.a1=10);
+----+--------------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
| id | select_type        | table | type  | possible_keys | key      | key_len | ref  | rows  | filtered | Extra                    |
+----+--------------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
|  1 | PRIMARY            | t1    | ALL   | NULL          | NULL     | NULL    | NULL | 10157 |   100.00 | Using where              |
|  2 | DEPENDENT SUBQUERY | t2    | index | NULL          | t_idx_t2 | 5       | NULL | 10157 |   100.00 | Using where; Using index |
+----+--------------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
2 rows in set, 2 warnings (0.00 sec)

root@[test] 15:26:33>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1276
Message: Field or reference 'test.t1.a1' of SELECT #2 was resolved in SELECT #1
*************************** 2. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where <nop>(<in_optimizer>(`test`.`t1`.`a1`,<exists>(/* select#2 */ select 1 from `test`.`t2` where ((`test`.`t1`.`a1` = 10) and <if>(outer_field_is_not_null, ((<cache>(`test`.`t1`.`a1`) < `test`.`t2`.`a2`) or isnull(`test`.`t2`.`a2`)), true)) having <if>(outer_field_is_not_null, <is_not_null_test>(`test`.`t2`.`a2`), true))))
2 rows in set (0.00 sec)

ERROR: 
No query specified

mariadb 10.0.2:
root@[test] 15:24:22>explain extended select * from t1 where t1.a1<any(select a2 from t2 where t1.a1=10);
+------+--------------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
| id   | select_type        | table | type  | possible_keys | key      | key_len | ref  | rows  | filtered | Extra                    |
+------+--------------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
|    1 | PRIMARY            | t1    | ALL   | NULL          | NULL     | NULL    | NULL | 10157 |   100.00 | Using where              |
|    2 | DEPENDENT SUBQUERY | t2    | index | NULL          | t_idx_t2 | 5       | NULL | 10157 |   100.00 | Using where; Using index |
+------+--------------------+-------+-------+---------------+----------+---------+------+-------+----------+--------------------------+
2 rows in set, 2 warnings (0.00 sec)

root@[test] 15:26:41>show warnings\G;
*************************** 1. row ***************************
  Level: Note
   Code: 1276
Message: Field or reference 'test.t1.a1' of SELECT #2 was resolved in SELECT #1
*************************** 2. row ***************************
  Level: Note
   Code: 1003
Message: select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`b1` AS `b1` from `test`.`t1` where <nop>(<expr_cache><`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t1`.`a1`,<exists>(select `test`.`t2`.`a2` from `test`.`t2` where ((`test`.`t1`.`a1` = 10) and trigcond(((<cache>(`test`.`t1`.`a1`) < `test`.`t2`.`a2`) or isnull(`test`.`t2`.`a2`)))) having trigcond(<is_not_null_test>(`test`.`t2`.`a2`))))))
2 rows in set (0.00 sec)

ERROR: No query specified

对关联子查询,子查询存在,使用了exists优化。

总结:
对>some和>any非关联子查询使用min函数,对<some和<any非关联子查询使用max函数,=any和=some子查询使用半连接进行优化,对>some和>any关联子查询以及<some和<any关联子查询只有exists优化。





转载于:https://my.oschina.net/anthonyyau/blog/296851

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值