目录
1 使用union all 替换 union实现sql优化案例
方案4:使用union all对结果集进行求并集,不需要去重
1 使用union all 替换 union实现sql优化案例
1.1 问题背景
员工表:employees,数据大概300024条(30万),定义如下:
CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` enum('M','F') NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
现有以下需求:需要查询工号emp_no=10001或者10010的员工信息,该需求可以用以下4种sql来实现,emp_no是主键,不重复。这实际上是一个典型的多值匹配问题。
1.2 解决方案
方案1 :用in来实现范围查询
select e1.* from employees e1 where e1.emp_no in (10001,10010);
可以看出使用in条件,会使用主键索引,访问方式为range索引范围查询,并且使用where条件来实现数据筛选。
方案2 :用or条件来实现多值匹配
select e1.* from employees e1 where e1.emp_no =10001 or e1.emp_no = 10010;
与方案1结果完全相同。
方案3:使用union对结果集进行求并集,需要去重
select e1.* from employees e1 where e1.emp_no = 10001
union
select e2.* from employees e2 where e2.emp_no = 10010
但是我们从执行计划中观察到,有3条执行计划,这是因为union是默认要对两个结果集进行去重的,其工作原理是先把结果集1中的数据记录插入到一张临时表中,然后,遍历结果集2中的数据记录,判断两条记录中的所有的字段值都相等,则判定为重复,则忽略;如果不重复,则插入到临时表中。所以union all有一个不好的地方,就是要用临时表来实现去重,而这个过程是非常消耗性能的。所以我们明知两个结果集不可能重复,所以我们就一定不要使用union。
方案4:使用union all对结果集进行求并集,不需要去重
select e1.* from employees e1 where e1.emp_no = 10001
union all
select e2.* from employees e2 where e2.emp_no = 10010
与方案1、方案2、方案3相比,这个执行计划是优的,并且执行时间也是最短的。
所以我们一定要清楚union all 与 union 的区别,正确的选择union 、union all是每个
开发人员应该具备的素养。