常量传递规则在表关联场景中的体现

130 阅读1分钟

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一个小知识点了~