分类: Mysql/postgreSQL
2015-03-08 22:46:46
原文地址:Mysql谓词下推技术 作者:oracle狂热分子
Mysql谓词下推技术
上次和一个朋友在讨论一个Mysql连接的优化,他的观点是有对于
where条件的限制的表,可以先对这个表写一个from视图,在视图中先
用where条件做限制,然后再来做连接
原始语句是这样的
select *
from sbtest t1 join snapshot t2 on t1.id=t2.id
where t2.snap_id=1420637262
改成如下的形式
select *
from sbtest t1 join (select * from snapshot where snap_id=1420637262) t2
on t1.id=t2.id
这种观点主要是思想是对于有where条件限制的表,先尽量做限制。但是这种方式真的会执行率高吗? 我们首先来看看执行计划
mysql> explain
-> select *
-> from sbtest t1 join (select * from snapshot where snap_id=1420637262) t2
-> on t1.id=t2.id;
+----+-------------+------------+--------+---------------+---------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+---------------+---------+---------+-------+------+-------------+
| 1 | PRIMARY |
| 1 | PRIMARY | t1 | eq_ref | PRIMARY | PRIMARY | 4 | t2.id | 1 | Using where |
| 2 | DERIVED | snapshot | ALL | NULL | NULL | NULL | NULL | 5846 | Using where |
+----+-------------+------------+--------+---------------+---------+---------+-------+------+-------------+
3 rows in set (0.00 sec)
首先看id为2的,对子查询做一个全表扫描,然后使用where条件过滤.结果再驱动到id为1
再来看看原始语句的执行计划
mysql> explain
-> select *
-> from sbtest t1 join snapshot t2 on t1.id=t2.id
-> where t2.snap_id=1420637262;
+----+-------------+-------+--------+---------------+---------+---------+-----------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+---------+---------+-----------+------+-------------+
| 1 | SIMPLE | t2 | ALL | PRIMARY | NULL | NULL | NULL | 5846 | Using where |
| 1 | SIMPLE | t1 | eq_ref | PRIMARY | PRIMARY | 4 | db1.t2.id | 1 | Using where |
+----+-------------+-------+--------+---------------+---------+---------+-----------+------+-------------+
2 rows in set (0.00 sec)
在这里首先是对t2表进行全表扫描,但是where条件是在扫描t2的时候过滤还是连接过后过滤呢?通过执行计划我们可以很明显可以看出是后一种方式,在对t2表进行全表扫描后,使用where条件过滤,然后结果只有一行了,注意执行计划的第二行的 type=eq_ref,后面的rows为1 。
我们这种方式叫作谓词下推技术,事实主流的数据库基本上都支持这种方式的优化。其原则是在一个查询树中,对于
任何选择都尽量早做选择,然后进行一步的处理.可见我们并不需要改写这个sql,优化器会自动去帮我们做这种优化.