SQL语句
select t1.id,t1.a,t2.id
from t1
join t2
on t1.a=t2.id
where t1.a=123 and t1.b=xxx and t1.xxx=
说明:由于生产数据敏感,因此写成比较简单的语句了
- 在之前的认知中,本来以为t1的条件更多,t2上没有条件,理应选择t1作为驱动表,不过实际上是选择了t2作为驱动表,执行计划如下:
mysql> explain select t1.id,t1.a,t2.id from t1 join t2 on t1.a=t2.id where t1.a=123;
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
| 1 | SIMPLE | t2 | NULL | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.00 | Using index |
| 1 | SIMPLE | t1 | NULL | ref | a | a | 5 | const | 1 | 100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)
这是因为优化器在生成执行计划之前会进行SQL改写,其中有一条规则是“常量传递”,文字描述为:
- 当某个表达式是某个列和某个常量做等值匹配,这个表达式和其他涉及该列的表达式使用AND连接起来时,可以将其他涉及该列的表达式中,该列名替换为常量,例如:
a = 5 AND b > a 转化为 a = 5 AND b > 5
在最初的表连接SQL中:
- t1和t2表通过t1.a=t2.id进行关联,同时又有条件t1.a=123,则根据常量传递规则,有隐性的条件t2.id=123,t2.id为表的主键,因此在t2中只有一条记录,则根据小结果集的表作为驱动表的规则,选择t2表作为驱动表
也算get一个小知识点了~