它们生成非常相似的执行计划(在我的测试表上,它们很小;YMMV,始终分析真实数据),您可能需要考虑第三种替代方案:
第一个:
EXPLAIN SELECT * FROM aTable WHERE aField in (SELECT xField FROM bTable WHERE yField > 5);
+----+--------------------+--------+-------+---------------+---------------+---------+------+------+-------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+--------------------+--------+-------+---------------+---------------+---------+------+------+-------------+| 1 | PRIMARY | aTable | ALL | NULL | NULL | NULL | NULL | 4 | Using where || 2 | DEPENDENT SUBQUERY | bTable | range | bTable_yField | bTable_yField | 5 | NULL | 2 | Using where |+----+--------------------+--------+-------+---------------+---------------+---------+------+------+-------------+
The second:
EXPLAIN SELECT * FROM aTable WHERE (SELECT yField FROM bTable WHERE aTable.aField = bTable.xField) > 5;
+----+--------------------+--------+------+---------------+------+---------+------+------+-------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+--------------------+--------+------+---------------+------+---------+------+------+-------------+| 1 | PRIMARY | aTable | ALL | NULL | NULL | NULL | NULL | 4 | Using where || 2 | DEPENDENT SUBQUERY | bTable | ALL | NULL | NULL | NULL | NULL | 4 | Using where |+----+--------------------+--------+------+---------------+------+---------+------+------+-------------+
Both result in a dependent subquery; on my example tables, the first one gets the benefit of the index (I assume bTable.yField
is indexed) while the second doesn't.
You can avoid the dependent subquery and get better up-front filtering using a JOIN
:
The third alternative:
EXPLAIN SELECT * FROM aTable INNER JOIN bTable On aTable.aField = bTable.xField WHERE bTable.yField > 5;
+----+-------------+--------+-------+---------------+---------------+---------+------+------+--------------------------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+--------+-------+---------------+---------------+---------+------+------+--------------------------------+| 1 | SIMPLE | bTable | range | bTable_yField | bTable_yField | 5 | NULL | 2 | Using where || 1 | SIMPLE | aTable | ALL | NULL | NULL | NULL | NULL | 4 | Using where; Using join buffer |+----+-------------+--------+-------+---------------+---------------+---------+------+------+--------------------------------+
同样,您确实必须使用您的 架构和您的 具有代表性的真实世界数据进行分析,因为优化器可能会做出不同的决定。
在 this excellent article 中对这些技术进行了更多比较通过 quassnoi .
作为引用,下面是我如何创建 aTable
和 bTable
(因为您没有提供定义)并测试您的查询:
mysql> CREATE TABLE aTable (aField INT, aMore VARCHAR(200));Query OK, 0 rows affected (0.01 sec)mysql> CREATE TABLE bTable (xField INT, yField INT);Query OK, 0 rows affected (0.02 sec)mysql> INSERT INTO aTable (aField, aMore) VALUES (1, 'One'), (2, 'Two'), (3, 'Three'), (4, 'Four');Query OK, 4 rows affected (0.00 sec)Records: 4 Duplicates: 0 Warnings: 0mysql> INSERT INTO bTable (xField, yField) VALUES (1, 10), (2, 2), (3, 20), (4, 4);Query OK, 4 rows affected (0.02 sec)Records: 4 Duplicates: 0 Warnings: 0mysql> CREATE INDEX bTable_yField ON bTable(yField);Query OK, 0 rows affected (0.05 sec)Records: 0 Duplicates: 0 Warnings: 0mysql> SELECT * FROM aTable WHERE aField in (SELECT xField FROM bTable WHERE yField > 5);+--------+-------+| aField | aMore |+--------+-------+| 1 | One || 3 | Three |+--------+-------+2 rows in set (0.00 sec)mysql> SELECT * FROM aTable WHERE (SELECT yField FROM bTable WHERE aTable.aField = bTable.xField) > 5;+--------+-------+| aField | aMore |+--------+-------+| 1 | One || 3 | Three |+--------+-------+2 rows in set (0.00 sec)
我是一名优秀的程序员,十分优秀!